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 | 51x 51x 51x 51x 59x 59x 59x 59x 59x 59x 59x 59x 29x 29x 29x 17x 29x 29x 17x 27x 27x 27x 27x 2x 29x 244x | 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> }; }; }; |