From 32b9f83bbda8c535d20a0f9ac8fe4fd7fde4ff16 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Mon, 16 Dec 2024 15:53:01 +0530 Subject: [PATCH] feat: setup events API for HealthManager --- packages/core/src/lib/health_manager.ts | 49 +++++++++++++++++++++-- packages/interfaces/src/health_manager.ts | 17 ++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/packages/core/src/lib/health_manager.ts b/packages/core/src/lib/health_manager.ts index c41cf7950f..f7a823ba2a 100644 --- a/packages/core/src/lib/health_manager.ts +++ b/packages/core/src/lib/health_manager.ts @@ -1,4 +1,7 @@ import { + HealthEvent, + HealthEventType, + HealthListener, HealthStatus, type IHealthManager, NodeHealth, @@ -9,12 +12,14 @@ import { class HealthManager implements IHealthManager { public static instance: HealthManager; private readonly health: NodeHealth; + private listeners: Map>; private constructor() { this.health = { overallStatus: HealthStatus.Unhealthy, protocolStatuses: new Map() }; + this.listeners = new Map(); } public static getInstance(): HealthManager { @@ -51,9 +56,37 @@ class HealthManager implements IHealthManager { lastUpdate: new Date() }); + this.emitEvent({ + type: "health:protocol", + status, + protocol, + timestamp: new Date() + }); + this.updateOverallHealth(); } + public addEventListener( + type: HealthEventType, + listener: HealthListener + ): void { + if (!this.listeners.has(type)) { + this.listeners.set(type, new Set()); + } + this.listeners.get(type)?.add(listener); + } + + public removeEventListener( + type: HealthEventType, + listener: HealthListener + ): void { + this.listeners.get(type)?.delete(listener); + } + + private emitEvent(event: HealthEvent): void { + this.listeners.get(event.type)?.forEach((listener) => listener(event)); + } + private getNameFromMulticodec(multicodec: string): Protocols { let name: Protocols; if (multicodec.includes("filter")) { @@ -74,14 +107,24 @@ class HealthManager implements IHealthManager { (p) => this.getProtocolStatus(p)?.status ); + let newStatus: HealthStatus; if (statuses.some((status) => status === HealthStatus.Unhealthy)) { - this.health.overallStatus = HealthStatus.Unhealthy; + newStatus = HealthStatus.Unhealthy; } else if ( statuses.some((status) => status === HealthStatus.MinimallyHealthy) ) { - this.health.overallStatus = HealthStatus.MinimallyHealthy; + newStatus = HealthStatus.MinimallyHealthy; } else { - this.health.overallStatus = HealthStatus.SufficientlyHealthy; + newStatus = HealthStatus.SufficientlyHealthy; + } + + if (this.health.overallStatus !== newStatus) { + this.health.overallStatus = newStatus; + this.emitEvent({ + type: "health:overall", + status: newStatus, + timestamp: new Date() + }); } } } diff --git a/packages/interfaces/src/health_manager.ts b/packages/interfaces/src/health_manager.ts index 8d3a1a9863..c59e2a3c75 100644 --- a/packages/interfaces/src/health_manager.ts +++ b/packages/interfaces/src/health_manager.ts @@ -6,10 +6,27 @@ export enum HealthStatus { SufficientlyHealthy = "SufficientlyHealthy" } +export type HealthEventType = "health:overall" | "health:protocol"; + +export interface HealthEvent { + type: HealthEventType; + status: HealthStatus; + protocol?: Protocols; + timestamp: Date; +} + +export type HealthListener = (event: HealthEvent) => void; + export interface IHealthManager { getHealthStatus: () => HealthStatus; getProtocolStatus: (protocol: Protocols) => ProtocolHealth | undefined; updateProtocolHealth: (multicodec: string, connectedPeers: number) => void; + + addEventListener: (type: HealthEventType, listener: HealthListener) => void; + removeEventListener: ( + type: HealthEventType, + listener: HealthListener + ) => void; } export type NodeHealth = {