diff --git a/packages/api-sync/source/listeners/peers.ts b/packages/api-sync/source/listeners/peers.ts index 806ec5ad2..7e77390a1 100644 --- a/packages/api-sync/source/listeners/peers.ts +++ b/packages/api-sync/source/listeners/peers.ts @@ -17,6 +17,7 @@ export class Peers extends AbstractListener { protected getEventMapping(): ListenerEventMapping { return { [Events.PeerEvent.Added]: ListenerEvent.OnAdded, + [Events.PeerEvent.Updated]: ListenerEvent.OnAdded, // upsert [Events.PeerEvent.Removed]: ListenerEvent.OnRemoved, }; } diff --git a/packages/contracts/source/events.ts b/packages/contracts/source/events.ts index cab5eef75..733c43374 100644 --- a/packages/contracts/source/events.ts +++ b/packages/contracts/source/events.ts @@ -43,6 +43,7 @@ export enum PeerEvent { Disconnected = "peer.disconnected", Disconnecting = "peer.disconnecting", Removed = "peer.removed", + Updated = "peer.updated", } export enum ConsensusEvent { diff --git a/packages/p2p/source/peer-repository.test.ts b/packages/p2p/source/peer-repository.test.ts index ae3567ccb..c3e8cceca 100644 --- a/packages/p2p/source/peer-repository.test.ts +++ b/packages/p2p/source/peer-repository.test.ts @@ -8,11 +8,14 @@ describe<{ sandbox: Sandbox; peerRepository: PeerRepository; }>("PeerRepository", ({ it, assert, beforeEach }) => { + const eventDispatcher = { dispatch: () => {}, listen: () => {} }; + beforeEach((context) => { context.sandbox = new Sandbox(); context.sandbox.app.bind(Identifiers.Services.Queue.Factory).toConstantValue({}); context.sandbox.app.bind(Identifiers.ServiceProvider.Configuration).toConstantValue({}); + context.sandbox.app.bind(Identifiers.Services.EventDispatcher.Service).toConstantValue(eventDispatcher); context.peerRepository = context.sandbox.app.resolve(PeerRepository); }); diff --git a/packages/p2p/source/peer.test.ts b/packages/p2p/source/peer.test.ts index dbc4a5655..cab3fda96 100644 --- a/packages/p2p/source/peer.test.ts +++ b/packages/p2p/source/peer.test.ts @@ -10,10 +10,12 @@ describe<{ }>("Peer", ({ it, assert, beforeEach, each }) => { const ip = "167.184.53.78"; const port = 4000; + const eventDispatcher = { dispatch: () => {}, listen: () => {} }; beforeEach((context) => { context.sandbox = new Sandbox(); context.sandbox.app.bind(Identifiers.Services.Queue.Factory).toConstantValue({}); + context.sandbox.app.bind(Identifiers.Services.EventDispatcher.Service).toConstantValue(eventDispatcher); context.peer = context.sandbox.app.resolve(Peer).init(ip, port); }); diff --git a/packages/p2p/source/peer.ts b/packages/p2p/source/peer.ts index 4c1a7a68b..de9ab7696 100644 --- a/packages/p2p/source/peer.ts +++ b/packages/p2p/source/peer.ts @@ -1,5 +1,5 @@ import { inject, injectable } from "@mainsail/container"; -import { Contracts, Identifiers } from "@mainsail/contracts"; +import { Contracts, Events, Identifiers } from "@mainsail/contracts"; import { Types, Utils } from "@mainsail/kernel"; import dayjs, { Dayjs } from "dayjs"; @@ -10,6 +10,9 @@ export class Peer implements Contracts.P2P.Peer { @inject(Identifiers.Services.Queue.Factory) private readonly createQueue!: Types.QueueFactory; + @inject(Identifiers.Services.EventDispatcher.Service) + private readonly events!: Contracts.Kernel.EventDispatcher; + public ip!: string; public port!: number; @@ -54,7 +57,18 @@ export class Peer implements Contracts.P2P.Peer { } public set header(header: Contracts.P2P.HeaderData) { + const isUpdate = this.#header !== undefined; + this.#header = header; + + if (!isUpdate) { + return; + } + + const changed = header.height !== this.#header.height || header.version !== this.#header.version; + if (changed) { + void this.events.dispatch(Events.PeerEvent.Updated, this); + } } public recentlyPinged(): boolean { diff --git a/packages/p2p/source/service-provider.test.ts b/packages/p2p/source/service-provider.test.ts index ef31e5778..9c2359580 100644 --- a/packages/p2p/source/service-provider.test.ts +++ b/packages/p2p/source/service-provider.test.ts @@ -17,12 +17,14 @@ describe<{ const server = { boot: async () => {}, dispose: async () => {}, initialize: async () => {} }; const service = { boot: async () => {}, dispose: async () => {} }; const peerDisposer = { disposePeers: async () => {} }; + const eventDispatcher = { dispatch: () => {}, listen: () => {} }; beforeEach((context) => { context.sandbox = new Sandbox(); context.sandbox.app.bind(Identifiers.Services.Trigger.Service).toConstantValue(triggerService); context.sandbox.app.bind(Identifiers.Cryptography.Validator).toConstantValue(validator); + context.sandbox.app.bind(Identifiers.Services.EventDispatcher.Service).toConstantValue(eventDispatcher); context.serviceProvider = context.sandbox.app.resolve(ServiceProvider); }); diff --git a/packages/p2p/source/socket-server/controllers/get-peers.test.ts b/packages/p2p/source/socket-server/controllers/get-peers.test.ts index 1286cabea..08173a4b9 100644 --- a/packages/p2p/source/socket-server/controllers/get-peers.test.ts +++ b/packages/p2p/source/socket-server/controllers/get-peers.test.ts @@ -9,11 +9,13 @@ describe<{ controller: GetPeersController; }>("GetPeersController", ({ it, assert, beforeEach, stub }) => { const peerRepository = { getPeers: () => {} }; + const eventDispatcher = { dispatch: () => {}, listen: () => {} }; beforeEach((context) => { context.sandbox = new Sandbox(); context.sandbox.app.bind(Identifiers.P2P.Peer.Repository).toConstantValue(peerRepository); + context.sandbox.app.bind(Identifiers.Services.EventDispatcher.Service).toConstantValue(eventDispatcher); context.sandbox.app.bind(Identifiers.Services.Queue.Factory).toConstantValue({}); context.controller = context.sandbox.app.resolve(GetPeersController);