Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 44x 44x 44x 44x 59x 59x 59x 59x 59x 59x 59x 59x 29x 29x 29x 17x 29x 29x 17x 27x 27x 27x 27x 2x 29x 214x | import { Cardano, CardanoNode, HealthCheckResponse, Provider, ProviderDependencies } from '@cardano-sdk/core';
import { InMemoryCache } from '../../InMemoryCache';
import { LedgerTipModel, findLedgerTip } from './util';
import { Logger } from 'ts-log';
import { Pool } from 'pg';
/** Dedicated DB pools */
export interface DbPools {
/** Main operational db pool */
main: Pool;
/** Secondary health check db pool */
healthCheck: Pool;
}
/** Properties that are need to create DbSyncProvider */
export interface DbSyncProviderDependencies extends ProviderDependencies {
/** Cache engines. Default: InMemoryCache with HealthCheck.cacheTTL as default TTL */
cache: {
healthCheck: InMemoryCache;
};
/** DB pools */
dbPools: DbPools;
/** Ogmios Cardano Node provider */
cardanoNode: CardanoNode;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyArgs = any[];
export const findLedgerTipOptions = { name: 'find_ledger_tip', text: findLedgerTip } as const;
export const DbSyncProvider = <
T extends (abstract new (...args: AnyArgs) => {}) | (new (...args: AnyArgs) => {}) = { new (): {} }
>(
BaseClass?: T
) => {
abstract class Mixin extends (BaseClass || Object) implements Provider {
public dbPools: DbPools;
public cardanoNode: CardanoNode;
public logger: Logger;
#cache: {
healthCheck: InMemoryCache;
};
constructor(...args: AnyArgs) {
const [dependencies, ...baseArgs] = [...args] as [DbSyncProviderDependencies, ...AnyArgs];
const { cache, dbPools, cardanoNode, logger } = dependencies;
super(...baseArgs);
this.dbPools = dbPools;
this.cardanoNode = cardanoNode;
this.logger = logger;
this.#cache = cache;
}
/** Healthy if the tip of both the node and database can be accessed. */
public async healthCheck(): Promise<HealthCheckResponse> {
const response: HealthCheckResponse = { ok: false };
try {
const cardanoNode = await this.#cache.healthCheck.get('node_health', async () =>
this.cardanoNode.healthCheck()
);
response.localNode = cardanoNode.localNode;
const tip = await this.#cache.healthCheck.get(
'db_tip',
async () => (await this.dbPools.healthCheck.query<LedgerTipModel>(findLedgerTipOptions)).rows[0]
);
if (tip) {
response.projectedTip = {
blockNo: Cardano.BlockNo(tip.block_no),
hash: tip.hash.toString('hex') as unknown as Cardano.BlockId,
slot: Cardano.Slot(Number(tip.slot_no))
};
response.ok = cardanoNode.ok && !!tip?.block_no;
this.logger.debug(
`Service /health: projected block tip: ${tip.block_no},local node block tip: ${cardanoNode.localNode?.ledgerTip?.blockNo}.`
);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
this.logger.error(error.message);
}
return response;
}
}
type BaseArgs = T extends abstract new (...baseArgs: infer A) => {}
? A
: T extends new (...baseArgs: infer A) => {}
? A
: never;
type BaseInstance = T extends abstract new (...baseArgs: AnyArgs) => infer I
? I
: T extends new (...baseArgs: AnyArgs) => infer I
? I
: never;
type ReturnedType = BaseInstance & {
dbPools: DbPools;
cardanoNode: CardanoNode;
logger: Logger;
healthCheck: () => Promise<HealthCheckResponse>;
};
return Mixin as unknown as (T extends new (...baseArgs: AnyArgs) => {}
? new (dependencies: DbSyncProviderDependencies, ...args: BaseArgs) => ReturnedType
: abstract new (dependencies: DbSyncProviderDependencies, ...args: BaseArgs) => ReturnedType) & {
prototype: { healthCheck: () => Promise<HealthCheckResponse> };
};
};
|