Skip to content
This repository was archived by the owner on Apr 22, 2026. It is now read-only.

Commit 7d2874f

Browse files
committed
fix: service healthchecker checks all configured DAL and verifier endpoints for issues
1 parent 6d0c766 commit 7d2874f

3 files changed

Lines changed: 49 additions & 31 deletions

File tree

packages/fasset-bots-core/src/actors/service-health-checker.ts

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,41 @@ async function checkNativeRpcHealth(): Promise<string | undefined> {
2424
async function checkIndexerHealth(
2525
indexer: BlockchainIndexerHelper
2626
): Promise<string | undefined> {
27-
try {
28-
const ok = await indexer.getHealth()
29-
if (!ok) {
30-
return 'health check failed'
27+
const msgs: string[] = []
28+
for (const [i, client] of indexer.verifier.clients.entries()) {
29+
const url = indexer.indexerWebServerUrls[i]
30+
try {
31+
const healthy = await indexer.getHealth(client)
32+
if (!healthy) {
33+
msgs.push(`client ${url} is unhealthy`)
34+
}
35+
} catch (e: any) {
36+
msgs.push(`client ${url} connection errored with ${String(e?.message)}`)
3137
}
32-
} catch (e: any) {
33-
return String(e?.message)
38+
}
39+
if (msgs.length > 0) {
40+
return msgs.join(', ')
3441
}
3542
}
3643

44+
3745
async function checkDalHealth(
3846
fdc: FlareDataConnectorClientHelper
3947
): Promise<string | undefined> {
40-
try {
41-
const healthy = await fdc.getHealth()
42-
const n = healthy.filter(h => h).length
43-
if (n < fdc.dataAccessLayerClients.length) {
44-
const unhealthy = healthy.map((h, i) => h ? '' : fdc.dataAccessLayerUrls[i]).join(',')
45-
return `clients ${unhealthy} are healthy`
46-
} else if (n == 0) {
47-
return 'no clients available'
48+
const msgs: string[] = []
49+
for (const [i, client] of fdc.dataAccessLayerClients.entries()) {
50+
const url = fdc.dataAccessLayerUrls[i]
51+
try {
52+
const healthy = await fdc.getHealth(client)
53+
if (!healthy) {
54+
msgs.push(`client ${url} is unhealthy`)
55+
}
56+
} catch (e: any) {
57+
msgs.push(`client ${url} connection errored with ${String(e?.message)}`)
4858
}
49-
} catch (e: any) {
50-
return String(e?.message)
59+
}
60+
if (msgs.length > 0) {
61+
return msgs.join(', ')
5162
}
5263
}
5364

@@ -71,17 +82,20 @@ async function serviceHealthcheck(
7182
const errors: [string, string][] = []
7283
for (const c of config.fAssets.values()) {
7384
const rpcHealth = await checkNativeRpcHealth()
74-
const indexerHealth = await checkIndexerHealth(c.blockchainIndexerClient)
75-
// @ts-ignore flareDataConnector has the right implementation
76-
const dalHealth = await checkDalHealth(c.flareDataConnector)
77-
const walletHealth = await checkUnderlyingWalletHealth(c.wallet)
7885
if (rpcHealth != null) {
7986
errors.push(['Native RPC', rpcHealth])
80-
} else if (indexerHealth != null) {
87+
}
88+
const indexerHealth = await checkIndexerHealth(c.blockchainIndexerClient)
89+
if (indexerHealth != null) {
8190
errors.push(['FDC verifier', indexerHealth])
82-
} else if (dalHealth != null) {
91+
}
92+
// @ts-ignore flareDataConnector implements FlareDataConnectorClientHelper
93+
const dalHealth = await checkDalHealth(c.flareDataConnector)
94+
if (dalHealth != null) {
8395
errors.push(['DAL', dalHealth])
84-
} else if (walletHealth != null) {
96+
}
97+
const walletHealth = await checkUnderlyingWalletHealth(c.wallet)
98+
if (walletHealth != null) {
8599
errors.push(['Underlying RPC', walletHealth])
86100
}
87101
}

packages/fasset-bots-core/src/underlying-chain/BlockchainIndexerHelper.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import BN from "bn.js";
22
import { formatArgs } from "../utils/formatting";
33
import { DEFAULT_RETRIES, prefix0x, requireNotNull, retry, sleep, toBN, ZERO_BYTES32 } from "../utils/helpers";
44
import { logger } from "../utils/logger";
5+
import { HttpApiClient } from "../utils/HttpApiClient";
56
import { MultiApiClient } from "../utils/MultiApiClient";
67
import { ChainId } from "./ChainId";
78
import { IBlock, IBlockChain, IBlockId, ITransaction, TX_BLOCKED, TX_FAILED, TX_SUCCESS, TxInputOutput } from "./interfaces/IBlockChain";
@@ -202,9 +203,14 @@ export class BlockchainIndexerHelper implements IBlockChain {
202203
return blockHeight;
203204
}
204205

205-
async getHealth(): Promise<boolean> {
206-
const respdata = await this.verifier.get<ApiWrapper<boolean>>(`/api/health`, "getHealth");
207-
return respdata.status == "OK";
206+
async getHealth(client?: HttpApiClient): Promise<boolean> {
207+
if (client == null) {
208+
const respdata = await this.verifier.get<ApiWrapper<boolean>>(`/api/health`, "getHealth");
209+
return respdata.status == "OK";
210+
} else {
211+
const respdata = await client.get<ApiWrapper<boolean>>(`/api/health`, "getHealth", 0);
212+
return respdata.status == "OK";
213+
}
208214
}
209215

210216
async getCurrentBlockHeightFromIndexer(): Promise<number> {

packages/fasset-bots-core/src/underlying-chain/FlareDataConnectorClientHelper.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,9 @@ export class FlareDataConnectorClientHelper implements IFlareDataConnectorClient
257257
return proof;
258258
}
259259

260-
async getHealth(): Promise<boolean[]> {
261-
const responses = await Promise.all(this.dataAccessLayerClients.map(
262-
client => client.get<DalHealthResult>('/api/health', 'getHealth', 0))
263-
);
264-
return responses.map(r => r.healthy)
260+
async getHealth(client: HttpApiClient): Promise<boolean> {
261+
const response = await client.get<DalHealthResult>('/api/health', 'getHealth', 0);
262+
return response.healthy;
265263
}
266264

267265
/* istanbul ignore next */

0 commit comments

Comments
 (0)