@waku/core 0.0.34-c41b319.0 → 0.0.34-c43cec2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/bundle/{base_protocol-CCK9RCtH.js → base_protocol-DxFKDXX2.js} +20 -19
  2. package/bundle/{index-Db7LxDrL.js → index-yLOEQnIE.js} +39 -75
  3. package/bundle/index.js +133 -1815
  4. package/bundle/lib/base_protocol.js +2 -2
  5. package/bundle/lib/message/version_0.js +2 -2
  6. package/bundle/{version_0-ANFNAdFD.js → version_0-Che4t3mN.js} +42 -163
  7. package/dist/.tsbuildinfo +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/base_protocol.d.ts +2 -2
  12. package/dist/lib/base_protocol.js +2 -2
  13. package/dist/lib/base_protocol.js.map +1 -1
  14. package/dist/lib/connection_manager/connection_manager.d.ts +3 -56
  15. package/dist/lib/connection_manager/connection_manager.js +13 -96
  16. package/dist/lib/connection_manager/connection_manager.js.map +1 -1
  17. package/dist/lib/filter/index.d.ts +18 -1
  18. package/dist/lib/filter/index.js +208 -1
  19. package/dist/lib/filter/index.js.map +1 -1
  20. package/dist/lib/health_manager.d.ts +14 -0
  21. package/dist/lib/health_manager.js +70 -0
  22. package/dist/lib/health_manager.js.map +1 -0
  23. package/dist/lib/light_push/index.d.ts +15 -1
  24. package/dist/lib/light_push/index.js +144 -1
  25. package/dist/lib/light_push/index.js.map +1 -1
  26. package/dist/lib/metadata/index.d.ts +3 -1
  27. package/dist/lib/metadata/index.js +118 -1
  28. package/dist/lib/metadata/index.js.map +1 -1
  29. package/dist/lib/store/index.d.ts +9 -1
  30. package/dist/lib/store/index.js +82 -1
  31. package/dist/lib/store/index.js.map +1 -1
  32. package/dist/lib/stream_manager/stream_manager.d.ts +2 -2
  33. package/dist/lib/stream_manager/stream_manager.js +17 -16
  34. package/dist/lib/stream_manager/stream_manager.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/index.ts +2 -0
  37. package/src/lib/base_protocol.ts +3 -3
  38. package/src/lib/connection_manager/connection_manager.ts +20 -114
  39. package/src/lib/filter/index.ts +315 -1
  40. package/src/lib/health_manager.ts +90 -0
  41. package/src/lib/light_push/index.ts +189 -1
  42. package/src/lib/metadata/index.ts +182 -1
  43. package/src/lib/store/index.ts +136 -1
  44. package/src/lib/stream_manager/stream_manager.ts +18 -16
  45. package/dist/lib/filter/filter.d.ts +0 -18
  46. package/dist/lib/filter/filter.js +0 -209
  47. package/dist/lib/filter/filter.js.map +0 -1
  48. package/dist/lib/light_push/light_push.d.ts +0 -15
  49. package/dist/lib/light_push/light_push.js +0 -144
  50. package/dist/lib/light_push/light_push.js.map +0 -1
  51. package/dist/lib/metadata/metadata.d.ts +0 -3
  52. package/dist/lib/metadata/metadata.js +0 -119
  53. package/dist/lib/metadata/metadata.js.map +0 -1
  54. package/dist/lib/store/store.d.ts +0 -9
  55. package/dist/lib/store/store.js +0 -83
  56. package/dist/lib/store/store.js.map +0 -1
  57. package/src/lib/filter/filter.ts +0 -315
  58. package/src/lib/light_push/light_push.ts +0 -188
  59. package/src/lib/metadata/metadata.ts +0 -182
  60. package/src/lib/store/store.ts +0 -136
@@ -1,14 +1,5 @@
1
- import {
2
- type Connection,
3
- isPeerId,
4
- type Peer,
5
- type PeerId,
6
- type PeerInfo,
7
- type PeerStore,
8
- type Stream,
9
- TypedEventEmitter
10
- } from "@libp2p/interface";
11
- import { Multiaddr, multiaddr, MultiaddrInput } from "@multiformats/multiaddr";
1
+ import type { Peer, PeerId, PeerInfo, PeerStore } from "@libp2p/interface";
2
+ import { TypedEventEmitter } from "@libp2p/interface";
12
3
  import {
13
4
  ConnectionManagerOptions,
14
5
  DiscoveryTrigger,
@@ -239,60 +230,15 @@ export class ConnectionManager
239
230
  this.startNetworkStatusListener();
240
231
  }
241
232
 
242
- /**
243
- * Attempts to establish a connection with a peer and set up specified protocols.
244
- * The method handles both PeerId and Multiaddr inputs, manages connection attempts,
245
- * and maintains the connection state.
246
- *
247
- * The dialing process includes:
248
- * 1. Converting input to dialable peer info
249
- * 2. Managing parallel dial attempts
250
- * 3. Attempting to establish protocol-specific connections
251
- * 4. Handling connection failures and retries
252
- * 5. Updating the peer store and connection state
253
- *
254
- * @param {PeerId | MultiaddrInput} peer - The peer to connect to, either as a PeerId or multiaddr
255
- * @param {string[]} [protocolCodecs] - Optional array of protocol-specific codec strings to establish
256
- * (e.g., for LightPush, Filter, Store protocols)
257
- *
258
- * @throws {Error} If the multiaddr is missing a peer ID
259
- * @throws {Error} If the maximum dial attempts are reached and the peer cannot be dialed
260
- * @throws {Error} If there's an error deleting an undialable peer from the peer store
261
- *
262
- * @example
263
- * ```typescript
264
- * // Dial using PeerId
265
- * await connectionManager.dialPeer(peerId);
266
- *
267
- * // Dial using multiaddr with specific protocols
268
- * await connectionManager.dialPeer(multiaddr, [
269
- * "/vac/waku/relay/2.0.0",
270
- * "/vac/waku/lightpush/2.0.0-beta1"
271
- * ]);
272
- * ```
273
- *
274
- * @remarks
275
- * - The method implements exponential backoff through multiple dial attempts
276
- * - Maintains a queue for parallel dial attempts (limited by maxParallelDials)
277
- * - Integrates with the KeepAliveManager for connection maintenance
278
- * - Updates the peer store and connection state after successful/failed attempts
279
- * - If all dial attempts fail, triggers DNS discovery as a fallback
280
- */
281
- public async dialPeer(peer: PeerId | MultiaddrInput): Promise<Connection> {
282
- let connection: Connection | undefined;
283
- let peerId: PeerId | undefined;
284
- const peerDialInfo = this.getDialablePeerInfo(peer);
285
- const peerIdStr = isPeerId(peerDialInfo)
286
- ? peerDialInfo.toString()
287
- : peerDialInfo.getPeerId()!;
288
-
233
+ private async dialPeer(peerId: PeerId): Promise<void> {
289
234
  this.currentActiveParallelDialCount += 1;
290
235
  let dialAttempt = 0;
291
236
  while (dialAttempt < this.options.maxDialAttemptsForPeer) {
292
237
  try {
293
- log.info(`Dialing peer ${peerDialInfo} on attempt ${dialAttempt + 1}`);
294
- connection = await this.libp2p.dial(peerDialInfo);
295
- peerId = connection.remotePeer;
238
+ log.info(
239
+ `Dialing peer ${peerId.toString()} on attempt ${dialAttempt + 1}`
240
+ );
241
+ await this.libp2p.dial(peerId);
296
242
 
297
243
  const tags = await this.getTagNamesForPeer(peerId);
298
244
  // add tag to connection describing discovery mechanism
@@ -311,17 +257,21 @@ export class ConnectionManager
311
257
  } catch (error) {
312
258
  if (error instanceof AggregateError) {
313
259
  // Handle AggregateError
314
- log.error(`Error dialing peer ${peerIdStr} - ${error.errors}`);
260
+ log.error(
261
+ `Error dialing peer ${peerId.toString()} - ${error.errors}`
262
+ );
315
263
  } else {
316
264
  // Handle generic error
317
265
  log.error(
318
- `Error dialing peer ${peerIdStr} - ${(error as any).message}`
266
+ `Error dialing peer ${peerId.toString()} - ${
267
+ (error as any).message
268
+ }`
319
269
  );
320
270
  }
321
- this.dialErrorsForPeer.set(peerIdStr, error);
271
+ this.dialErrorsForPeer.set(peerId.toString(), error);
322
272
 
323
273
  dialAttempt++;
324
- this.dialAttemptsForPeer.set(peerIdStr, dialAttempt);
274
+ this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt);
325
275
  }
326
276
  }
327
277
 
@@ -332,7 +282,7 @@ export class ConnectionManager
332
282
  // If max dial attempts reached and dialing failed, delete the peer
333
283
  if (dialAttempt === this.options.maxDialAttemptsForPeer) {
334
284
  try {
335
- const error = this.dialErrorsForPeer.get(peerIdStr);
285
+ const error = this.dialErrorsForPeer.get(peerId.toString());
336
286
 
337
287
  if (error) {
338
288
  let errorMessage;
@@ -349,65 +299,21 @@ export class ConnectionManager
349
299
  }
350
300
 
351
301
  log.info(
352
- `Deleting undialable peer ${peerIdStr} from peer store. Reason: ${errorMessage}`
302
+ `Deleting undialable peer ${peerId.toString()} from peer store. Reason: ${errorMessage}`
353
303
  );
354
304
  }
355
305
 
356
- this.dialErrorsForPeer.delete(peerIdStr);
357
- if (peerId) {
358
- await this.libp2p.peerStore.delete(peerId);
359
- }
306
+ this.dialErrorsForPeer.delete(peerId.toString());
307
+ await this.libp2p.peerStore.delete(peerId);
360
308
 
361
309
  // if it was last available peer - attempt DNS discovery
362
310
  await this.attemptDnsDiscovery();
363
311
  } catch (error) {
364
312
  throw new Error(
365
- `Error deleting undialable peer ${peerIdStr} from peer store - ${error}`
313
+ `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`
366
314
  );
367
315
  }
368
316
  }
369
-
370
- if (!connection) {
371
- throw new Error(`Failed to dial peer ${peerDialInfo}`);
372
- }
373
-
374
- return connection;
375
- }
376
-
377
- /**
378
- * Dial a peer with specific protocols.
379
- * This method is a raw proxy to the libp2p dialProtocol method.
380
- * @param peer - The peer to connect to, either as a PeerId or multiaddr
381
- * @param protocolCodecs - Optional array of protocol-specific codec strings to establish
382
- * @returns A stream to the peer
383
- */
384
- public async rawDialPeerWithProtocols(
385
- peer: PeerId | MultiaddrInput,
386
- protocolCodecs: string[]
387
- ): Promise<Stream> {
388
- const peerDialInfo = this.getDialablePeerInfo(peer);
389
- return await this.libp2p.dialProtocol(peerDialInfo, protocolCodecs);
390
- }
391
-
392
- /**
393
- * Internal utility to extract a PeerId or Multiaddr from a peer input.
394
- * This is used internally by the connection manager to handle different peer input formats.
395
- * @internal
396
- */
397
- private getDialablePeerInfo(
398
- peer: PeerId | MultiaddrInput
399
- ): PeerId | Multiaddr {
400
- if (isPeerId(peer)) {
401
- return peer;
402
- } else {
403
- // peer is of MultiaddrInput type
404
- const ma = multiaddr(peer);
405
- const peerIdStr = ma.getPeerId();
406
- if (!peerIdStr) {
407
- throw new Error("Failed to dial multiaddr: missing peer ID");
408
- }
409
- return ma;
410
- }
411
317
  }
412
318
 
413
319
  private async attemptDnsDiscovery(): Promise<void> {
@@ -1 +1,315 @@
1
- export { FilterCodecs, FilterCore } from "./filter.js";
1
+ import type { Peer, Stream } from "@libp2p/interface";
2
+ import type { IncomingStreamData } from "@libp2p/interface-internal";
3
+ import {
4
+ type ContentTopic,
5
+ type CoreProtocolResult,
6
+ type IBaseProtocolCore,
7
+ type Libp2p,
8
+ ProtocolError,
9
+ type PubsubTopic
10
+ } from "@waku/interfaces";
11
+ import { WakuMessage } from "@waku/proto";
12
+ import { Logger } from "@waku/utils";
13
+ import all from "it-all";
14
+ import * as lp from "it-length-prefixed";
15
+ import { pipe } from "it-pipe";
16
+ import { Uint8ArrayList } from "uint8arraylist";
17
+
18
+ import { BaseProtocol } from "../base_protocol.js";
19
+
20
+ import {
21
+ FilterPushRpc,
22
+ FilterSubscribeResponse,
23
+ FilterSubscribeRpc
24
+ } from "./filter_rpc.js";
25
+
26
+ const log = new Logger("filter:v2");
27
+
28
+ export const FilterCodecs = {
29
+ SUBSCRIBE: "/vac/waku/filter-subscribe/2.0.0-beta1",
30
+ PUSH: "/vac/waku/filter-push/2.0.0-beta1"
31
+ };
32
+
33
+ export class FilterCore extends BaseProtocol implements IBaseProtocolCore {
34
+ public constructor(
35
+ private handleIncomingMessage: (
36
+ pubsubTopic: PubsubTopic,
37
+ wakuMessage: WakuMessage,
38
+ peerIdStr: string
39
+ ) => Promise<void>,
40
+ public readonly pubsubTopics: PubsubTopic[],
41
+ libp2p: Libp2p
42
+ ) {
43
+ super(FilterCodecs.SUBSCRIBE, libp2p.components, pubsubTopics);
44
+
45
+ libp2p
46
+ .handle(FilterCodecs.PUSH, this.onRequest.bind(this), {
47
+ maxInboundStreams: 100
48
+ })
49
+ .catch((e) => {
50
+ log.error("Failed to register ", FilterCodecs.PUSH, e);
51
+ });
52
+ }
53
+
54
+ public async subscribe(
55
+ pubsubTopic: PubsubTopic,
56
+ peer: Peer,
57
+ contentTopics: ContentTopic[]
58
+ ): Promise<CoreProtocolResult> {
59
+ const stream = await this.getStream(peer);
60
+
61
+ const request = FilterSubscribeRpc.createSubscribeRequest(
62
+ pubsubTopic,
63
+ contentTopics
64
+ );
65
+
66
+ let res: Uint8ArrayList[] | undefined;
67
+ try {
68
+ res = await pipe(
69
+ [request.encode()],
70
+ lp.encode,
71
+ stream,
72
+ lp.decode,
73
+ async (source) => await all(source)
74
+ );
75
+ } catch (error) {
76
+ log.error("Failed to send subscribe request", error);
77
+ return {
78
+ success: null,
79
+ failure: {
80
+ error: ProtocolError.GENERIC_FAIL,
81
+ peerId: peer.id
82
+ }
83
+ };
84
+ }
85
+
86
+ const { statusCode, requestId, statusDesc } =
87
+ FilterSubscribeResponse.decode(res[0].slice());
88
+
89
+ if (statusCode < 200 || statusCode >= 300) {
90
+ log.error(
91
+ `Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
92
+ );
93
+ return {
94
+ failure: {
95
+ error: ProtocolError.REMOTE_PEER_REJECTED,
96
+ peerId: peer.id
97
+ },
98
+ success: null
99
+ };
100
+ }
101
+
102
+ return {
103
+ failure: null,
104
+ success: peer.id
105
+ };
106
+ }
107
+
108
+ public async unsubscribe(
109
+ pubsubTopic: PubsubTopic,
110
+ peer: Peer,
111
+ contentTopics: ContentTopic[]
112
+ ): Promise<CoreProtocolResult> {
113
+ let stream: Stream | undefined;
114
+ try {
115
+ stream = await this.getStream(peer);
116
+ } catch (error) {
117
+ log.error(
118
+ `Failed to get a stream for remote peer${peer.id.toString()}`,
119
+ error
120
+ );
121
+ return {
122
+ success: null,
123
+ failure: {
124
+ error: ProtocolError.NO_STREAM_AVAILABLE,
125
+ peerId: peer.id
126
+ }
127
+ };
128
+ }
129
+
130
+ const unsubscribeRequest = FilterSubscribeRpc.createUnsubscribeRequest(
131
+ pubsubTopic,
132
+ contentTopics
133
+ );
134
+
135
+ try {
136
+ await pipe([unsubscribeRequest.encode()], lp.encode, stream.sink);
137
+ } catch (error) {
138
+ log.error("Failed to send unsubscribe request", error);
139
+ return {
140
+ success: null,
141
+ failure: {
142
+ error: ProtocolError.GENERIC_FAIL,
143
+ peerId: peer.id
144
+ }
145
+ };
146
+ }
147
+
148
+ return {
149
+ success: peer.id,
150
+ failure: null
151
+ };
152
+ }
153
+
154
+ public async unsubscribeAll(
155
+ pubsubTopic: PubsubTopic,
156
+ peer: Peer
157
+ ): Promise<CoreProtocolResult> {
158
+ const stream = await this.getStream(peer);
159
+
160
+ const request = FilterSubscribeRpc.createUnsubscribeAllRequest(pubsubTopic);
161
+
162
+ const res = await pipe(
163
+ [request.encode()],
164
+ lp.encode,
165
+ stream,
166
+ lp.decode,
167
+ async (source) => await all(source)
168
+ );
169
+
170
+ if (!res || !res.length) {
171
+ return {
172
+ failure: {
173
+ error: ProtocolError.NO_RESPONSE,
174
+ peerId: peer.id
175
+ },
176
+ success: null
177
+ };
178
+ }
179
+
180
+ const { statusCode, requestId, statusDesc } =
181
+ FilterSubscribeResponse.decode(res[0].slice());
182
+
183
+ if (statusCode < 200 || statusCode >= 300) {
184
+ log.error(
185
+ `Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
186
+ );
187
+ return {
188
+ failure: {
189
+ error: ProtocolError.REMOTE_PEER_REJECTED,
190
+ peerId: peer.id
191
+ },
192
+ success: null
193
+ };
194
+ }
195
+
196
+ return {
197
+ failure: null,
198
+ success: peer.id
199
+ };
200
+ }
201
+
202
+ public async ping(peer: Peer): Promise<CoreProtocolResult> {
203
+ let stream: Stream | undefined;
204
+ try {
205
+ stream = await this.getStream(peer);
206
+ } catch (error) {
207
+ log.error(
208
+ `Failed to get a stream for remote peer${peer.id.toString()}`,
209
+ error
210
+ );
211
+ return {
212
+ success: null,
213
+ failure: {
214
+ error: ProtocolError.NO_STREAM_AVAILABLE,
215
+ peerId: peer.id
216
+ }
217
+ };
218
+ }
219
+
220
+ const request = FilterSubscribeRpc.createSubscriberPingRequest();
221
+
222
+ let res: Uint8ArrayList[] | undefined;
223
+ try {
224
+ res = await pipe(
225
+ [request.encode()],
226
+ lp.encode,
227
+ stream,
228
+ lp.decode,
229
+ async (source) => await all(source)
230
+ );
231
+ } catch (error) {
232
+ log.error("Failed to send ping request", error);
233
+ return {
234
+ success: null,
235
+ failure: {
236
+ error: ProtocolError.GENERIC_FAIL,
237
+ peerId: peer.id
238
+ }
239
+ };
240
+ }
241
+
242
+ if (!res || !res.length) {
243
+ return {
244
+ success: null,
245
+ failure: {
246
+ error: ProtocolError.NO_RESPONSE,
247
+ peerId: peer.id
248
+ }
249
+ };
250
+ }
251
+
252
+ const { statusCode, requestId, statusDesc } =
253
+ FilterSubscribeResponse.decode(res[0].slice());
254
+
255
+ if (statusCode < 200 || statusCode >= 300) {
256
+ log.error(
257
+ `Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
258
+ );
259
+ return {
260
+ success: null,
261
+ failure: {
262
+ error: ProtocolError.REMOTE_PEER_REJECTED,
263
+ peerId: peer.id
264
+ }
265
+ };
266
+ }
267
+ return {
268
+ success: peer.id,
269
+ failure: null
270
+ };
271
+ }
272
+
273
+ private onRequest(streamData: IncomingStreamData): void {
274
+ const { connection, stream } = streamData;
275
+ const { remotePeer } = connection;
276
+ log.info(`Received message from ${remotePeer.toString()}`);
277
+ try {
278
+ pipe(stream, lp.decode, async (source) => {
279
+ for await (const bytes of source) {
280
+ const response = FilterPushRpc.decode(bytes.slice());
281
+
282
+ const { pubsubTopic, wakuMessage } = response;
283
+
284
+ if (!wakuMessage) {
285
+ log.error("Received empty message");
286
+ return;
287
+ }
288
+
289
+ if (!pubsubTopic) {
290
+ log.error("Pubsub topic missing from push message");
291
+ return;
292
+ }
293
+
294
+ await this.handleIncomingMessage(
295
+ pubsubTopic,
296
+ wakuMessage,
297
+ connection.remotePeer.toString()
298
+ );
299
+ }
300
+ }).then(
301
+ () => {
302
+ log.info("Receiving pipe closed.");
303
+ },
304
+ async (e) => {
305
+ log.error(
306
+ `Error with receiving pipe on peer:${connection.remotePeer.toString()} -- stream:${stream.id} -- protocol:${stream.protocol}: `,
307
+ e
308
+ );
309
+ }
310
+ );
311
+ } catch (e) {
312
+ log.error("Error decoding message", e);
313
+ }
314
+ }
315
+ }
@@ -0,0 +1,90 @@
1
+ import {
2
+ HealthStatus,
3
+ type IHealthManager,
4
+ NodeHealth,
5
+ type ProtocolHealth,
6
+ Protocols
7
+ } from "@waku/interfaces";
8
+
9
+ class HealthManager implements IHealthManager {
10
+ public static instance: HealthManager;
11
+ private readonly health: NodeHealth;
12
+
13
+ private constructor() {
14
+ this.health = {
15
+ overallStatus: HealthStatus.Unhealthy,
16
+ protocolStatuses: new Map()
17
+ };
18
+ }
19
+
20
+ public static getInstance(): HealthManager {
21
+ if (!HealthManager.instance) {
22
+ HealthManager.instance = new HealthManager();
23
+ }
24
+ return HealthManager.instance;
25
+ }
26
+
27
+ public getHealthStatus(): HealthStatus {
28
+ return this.health.overallStatus;
29
+ }
30
+
31
+ public getProtocolStatus(protocol: Protocols): ProtocolHealth | undefined {
32
+ return this.health.protocolStatuses.get(protocol);
33
+ }
34
+
35
+ public updateProtocolHealth(
36
+ multicodec: string,
37
+ connectedPeers: number
38
+ ): void {
39
+ const protocol = this.getNameFromMulticodec(multicodec);
40
+
41
+ let status: HealthStatus = HealthStatus.Unhealthy;
42
+ if (connectedPeers == 1) {
43
+ status = HealthStatus.MinimallyHealthy;
44
+ } else if (connectedPeers >= 2) {
45
+ status = HealthStatus.SufficientlyHealthy;
46
+ }
47
+
48
+ this.health.protocolStatuses.set(protocol, {
49
+ name: protocol,
50
+ status: status,
51
+ lastUpdate: new Date()
52
+ });
53
+
54
+ this.updateOverallHealth();
55
+ }
56
+
57
+ private getNameFromMulticodec(multicodec: string): Protocols {
58
+ let name: Protocols;
59
+ if (multicodec.includes("filter")) {
60
+ name = Protocols.Filter;
61
+ } else if (multicodec.includes("lightpush")) {
62
+ name = Protocols.LightPush;
63
+ } else if (multicodec.includes("store")) {
64
+ name = Protocols.Store;
65
+ } else {
66
+ throw new Error(`Unknown protocol: ${multicodec}`);
67
+ }
68
+ return name;
69
+ }
70
+
71
+ private updateOverallHealth(): void {
72
+ const relevantProtocols = [Protocols.LightPush, Protocols.Filter];
73
+ const statuses = relevantProtocols.map(
74
+ (p) => this.getProtocolStatus(p)?.status
75
+ );
76
+
77
+ if (statuses.some((status) => status === HealthStatus.Unhealthy)) {
78
+ this.health.overallStatus = HealthStatus.Unhealthy;
79
+ } else if (
80
+ statuses.some((status) => status === HealthStatus.MinimallyHealthy)
81
+ ) {
82
+ this.health.overallStatus = HealthStatus.MinimallyHealthy;
83
+ } else {
84
+ this.health.overallStatus = HealthStatus.SufficientlyHealthy;
85
+ }
86
+ }
87
+ }
88
+
89
+ export const getHealthManager = (): HealthManager =>
90
+ HealthManager.getInstance();