@eclesia/indexer-engine 2.10.0 → 2.11.1
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.
- package/dist/_virtual/rolldown_runtime.cjs +4 -0
- package/dist/_virtual/rolldown_runtime.mjs +38 -0
- package/dist/constants.cjs +6 -2
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +6 -3
- package/dist/constants.d.cts.map +1 -1
- package/dist/{constants.d.ts → constants.d.mts} +7 -4
- package/dist/constants.d.mts.map +1 -0
- package/dist/{constants.js → constants.mjs} +7 -4
- package/dist/constants.mjs.map +1 -0
- package/dist/emitter/index.cjs +6 -3
- package/dist/emitter/index.cjs.map +1 -1
- package/dist/emitter/index.d.cts.map +1 -1
- package/dist/emitter/{index.d.ts → index.d.mts} +2 -2
- package/dist/emitter/index.d.mts.map +1 -0
- package/dist/emitter/{index.js → index.mjs} +7 -4
- package/dist/emitter/index.mjs.map +1 -0
- package/dist/errors/index.cjs +18 -0
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/{index.d.ts → index.d.mts} +1 -1
- package/dist/errors/index.d.mts.map +1 -0
- package/dist/errors/{index.js → index.mjs} +19 -1
- package/dist/errors/index.mjs.map +1 -0
- package/dist/index.cjs +10 -2
- package/dist/index.d.cts +6 -5
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +12 -0
- package/dist/indexer/index.cjs +113 -67
- package/dist/indexer/index.cjs.map +1 -1
- package/dist/indexer/index.d.cts +7 -1
- package/dist/indexer/index.d.cts.map +1 -1
- package/dist/indexer/{index.d.ts → index.d.mts} +11 -5
- package/dist/indexer/index.d.mts.map +1 -0
- package/dist/indexer/{index.js → index.mjs} +121 -75
- package/dist/indexer/index.mjs.map +1 -0
- package/dist/metrics/index.cjs +28 -0
- package/dist/metrics/index.cjs.map +1 -1
- package/dist/metrics/index.d.cts.map +1 -1
- package/dist/metrics/{index.d.ts → index.d.mts} +1 -1
- package/dist/metrics/index.d.mts.map +1 -0
- package/dist/metrics/{index.js → index.mjs} +29 -1
- package/dist/metrics/index.mjs.map +1 -0
- package/dist/mocks/index.cjs +17 -0
- package/dist/mocks/index.cjs.map +1 -0
- package/dist/mocks/index.d.cts +9 -0
- package/dist/mocks/index.d.cts.map +1 -0
- package/dist/mocks/index.d.mts +9 -0
- package/dist/mocks/index.d.mts.map +1 -0
- package/dist/mocks/index.mjs +12 -0
- package/dist/mocks/index.mjs.map +1 -0
- package/dist/mocks/rpc-client.cjs +209 -0
- package/dist/mocks/rpc-client.cjs.map +1 -0
- package/dist/mocks/rpc-client.d.cts +44 -0
- package/dist/mocks/rpc-client.d.cts.map +1 -0
- package/dist/mocks/rpc-client.d.mts +44 -0
- package/dist/mocks/rpc-client.d.mts.map +1 -0
- package/dist/mocks/rpc-client.mjs +208 -0
- package/dist/mocks/rpc-client.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/ascii.cjs +32 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/ascii.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/ascii.mjs +29 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/ascii.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/base64.cjs +67 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/base64.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/base64.mjs +64 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/base64.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/bech32.cjs +80 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/bech32.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/bech32.mjs +77 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/bech32.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/hex.cjs +33 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/hex.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/hex.mjs +30 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/hex.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/index.cjs +106 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/index.mjs +103 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/index.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/rfc3339.cjs +52 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/rfc3339.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/rfc3339.mjs +49 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/rfc3339.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/utf8.cjs +31 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/utf8.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/utf8.mjs +28 -0
- package/dist/node_modules/.pnpm/@cosmjs_encoding@0.36.0/node_modules/@cosmjs/encoding/build/utf8.mjs.map +1 -0
- package/dist/node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.cjs +98 -0
- package/dist/node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.mjs +95 -0
- package/dist/node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.mjs.map +1 -0
- package/dist/promise-queue/index.cjs +34 -5
- package/dist/promise-queue/index.cjs.map +1 -1
- package/dist/promise-queue/index.d.cts.map +1 -1
- package/dist/promise-queue/{index.d.ts → index.d.mts} +1 -1
- package/dist/promise-queue/index.d.mts.map +1 -0
- package/dist/promise-queue/{index.js → index.mjs} +35 -6
- package/dist/promise-queue/index.mjs.map +1 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +2 -1
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/{index.d.ts → index.d.mts} +5 -4
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/{index.js → index.mjs} +1 -1
- package/dist/types/index.mjs.map +1 -0
- package/dist/utils/{bech32.d.ts → bech32.d.mts} +1 -1
- package/dist/utils/bech32.d.mts.map +1 -0
- package/dist/utils/{bech32.js → bech32.mjs} +1 -1
- package/dist/utils/bech32.mjs.map +1 -0
- package/dist/utils/{bigint.d.ts → bigint.d.mts} +1 -1
- package/dist/utils/bigint.d.mts.map +1 -0
- package/dist/utils/{bigint.js → bigint.mjs} +1 -1
- package/dist/utils/bigint.mjs.map +1 -0
- package/dist/utils/{index.d.ts → index.d.mts} +4 -4
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/{index.js → index.mjs} +5 -5
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/{text.d.ts → text.d.mts} +1 -1
- package/dist/utils/text.d.mts.map +1 -0
- package/dist/utils/{text.js → text.mjs} +1 -1
- package/dist/utils/text.mjs.map +1 -0
- package/dist/validation/{index.d.ts → index.d.mts} +1 -1
- package/dist/validation/index.d.mts.map +1 -0
- package/dist/validation/{index.js → index.mjs} +3 -3
- package/dist/validation/index.mjs.map +1 -0
- package/package.json +23 -20
- package/dist/_virtual/rolldown_runtime.js +0 -13
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/emitter/index.d.ts.map +0 -1
- package/dist/emitter/index.js.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js.map +0 -1
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -11
- package/dist/indexer/index.d.ts.map +0 -1
- package/dist/indexer/index.js.map +0 -1
- package/dist/metrics/index.d.ts.map +0 -1
- package/dist/metrics/index.js.map +0 -1
- package/dist/promise-queue/index.d.ts.map +0 -1
- package/dist/promise-queue/index.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/utils/bech32.d.ts.map +0 -1
- package/dist/utils/bech32.js.map +0 -1
- package/dist/utils/bigint.d.ts.map +0 -1
- package/dist/utils/bigint.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/text.d.ts.map +0 -1
- package/dist/utils/text.js.map +0 -1
- package/dist/validation/index.d.ts.map +0 -1
- package/dist/validation/index.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IndexerMetrics } from "../metrics/index.
|
|
2
|
-
import { EcleciaIndexerConfig, EmitFunc, WithHeightAndUUID } from "../types/index.
|
|
3
|
-
import { EclesiaEmitter } from "../emitter/index.
|
|
1
|
+
import { IndexerMetrics } from "../metrics/index.mjs";
|
|
2
|
+
import { EcleciaIndexerConfig, EmitFunc, WithHeightAndUUID } from "../types/index.mjs";
|
|
3
|
+
import { EclesiaEmitter } from "../emitter/index.mjs";
|
|
4
4
|
import { CometClient } from "@cosmjs/tendermint-rpc";
|
|
5
5
|
import * as winston from "winston";
|
|
6
6
|
|
|
@@ -16,6 +16,7 @@ declare const defaultIndexerConfig: {
|
|
|
16
16
|
pollingInterval: number;
|
|
17
17
|
shouldProcessGenesis: () => boolean;
|
|
18
18
|
minimal: boolean;
|
|
19
|
+
enableHealthcheck: boolean;
|
|
19
20
|
healthCheckPort: number;
|
|
20
21
|
enablePrometheus: boolean;
|
|
21
22
|
prometheusPort: number;
|
|
@@ -34,12 +35,14 @@ declare class EcleciaIndexer extends EclesiaEmitter {
|
|
|
34
35
|
private fastify;
|
|
35
36
|
/** Prometheus HTTP server instance */
|
|
36
37
|
private prometheusServer;
|
|
38
|
+
/** Indicates if the indexer has started */
|
|
39
|
+
private started;
|
|
37
40
|
/** Queue for managing block processing pipeline */
|
|
38
41
|
private blockQueue;
|
|
39
42
|
/** Latest block height from the chain */
|
|
40
43
|
private latestHeight;
|
|
41
44
|
/** Next block height to process */
|
|
42
|
-
|
|
45
|
+
heightToProcess: number;
|
|
43
46
|
/** Whether the indexer has been initialized */
|
|
44
47
|
private initialized;
|
|
45
48
|
/** Prometheus metrics server instance */
|
|
@@ -58,6 +61,8 @@ declare class EcleciaIndexer extends EclesiaEmitter {
|
|
|
58
61
|
private healthCheck;
|
|
59
62
|
/** WebSocket subscription for new block notifications */
|
|
60
63
|
private subscription;
|
|
64
|
+
/** Timeout handler for block reception */
|
|
65
|
+
private blockTimeout;
|
|
61
66
|
/**
|
|
62
67
|
* Creates a new Eclesia indexer instance
|
|
63
68
|
* @param config - Indexer configuration options
|
|
@@ -67,6 +72,7 @@ declare class EcleciaIndexer extends EclesiaEmitter {
|
|
|
67
72
|
private blockListener;
|
|
68
73
|
private isMinimal;
|
|
69
74
|
connect(): Promise<boolean>;
|
|
75
|
+
stop(): void;
|
|
70
76
|
start(): Promise<void>;
|
|
71
77
|
asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>>;
|
|
72
78
|
private processBlock;
|
|
@@ -81,4 +87,4 @@ declare class EcleciaIndexer extends EclesiaEmitter {
|
|
|
81
87
|
}
|
|
82
88
|
//#endregion
|
|
83
89
|
export { EcleciaIndexer, defaultIndexerConfig };
|
|
84
|
-
//# sourceMappingURL=index.d.
|
|
90
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/indexer/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAmEa;EAAA,WAAA,EAAA,MAAA;EAKS,SAAA,EAAA,MAAA;;;EAWa,QAAA,EAXb,oBAWa,CAAA,UAAA,CAAA;EAAA,UAAA,EAAA,OAAA;EAOtB,eAAA,EAAe,MAAA;EAEX,oBAAA,EAAA,GAAA,GAAA,OAAA;EAwBI,OAAA,EAAA,OAAA;EAMH,iBAAA,EAAA,OAAA;EAGK,eAAA,EAAA,MAAA;EAGT,gBAAQ,EAAA,OAAA;EAoBA,cAAA,EAAA,MAAA;EAoLA,IAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EA4BF,gBAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EA6MiC,cAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,GA9dlB,OA8dkB,CAAA,IAAA,CAAA;CAAlB;;;;;AAvdC,cAAvB,cAAA,SAAuB,cAAA,CAAA;EAAc;UAEjC;;;;;;;;;;;;;;;;cAwBI;;;;UAMH;;eAGK;;OAGT,OAAA,CAAQ;;;;;;;;;;;;;sBAoBA;;;;aAoLA;;WA4BF;aA6MA,eAAe,kBAAkB;;;+BAiTT,+CAAqD,QAAQ"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_START_HEIGHT, GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS } from "../constants.
|
|
2
|
-
import { EclesiaEmitter } from "../emitter/index.
|
|
3
|
-
import { IndexerMetrics } from "../metrics/index.
|
|
4
|
-
import { CircularBuffer } from "../promise-queue/index.
|
|
5
|
-
import { decodeAttr } from "../utils/text.
|
|
6
|
-
import "../utils/index.
|
|
7
|
-
import { validateFilePath, validatePort, validatePositiveInteger, validateUrl } from "../validation/index.
|
|
1
|
+
import { DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT, GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS } from "../constants.mjs";
|
|
2
|
+
import { EclesiaEmitter } from "../emitter/index.mjs";
|
|
3
|
+
import { IndexerMetrics } from "../metrics/index.mjs";
|
|
4
|
+
import { CircularBuffer } from "../promise-queue/index.mjs";
|
|
5
|
+
import { decodeAttr } from "../utils/text.mjs";
|
|
6
|
+
import "../utils/index.mjs";
|
|
7
|
+
import { validateFilePath, validatePort, validatePositiveInteger, validateUrl } from "../validation/index.mjs";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import * as fs from "node:fs";
|
|
10
10
|
import { connectComet, toRfc3339WithNanoseconds } from "@cosmjs/tendermint-rpc";
|
|
@@ -33,9 +33,10 @@ const defaultIndexerConfig = {
|
|
|
33
33
|
pollingInterval: DEFAULT_POLLING_INTERVAL_MS,
|
|
34
34
|
shouldProcessGenesis: () => false,
|
|
35
35
|
minimal: true,
|
|
36
|
+
enableHealthcheck: true,
|
|
36
37
|
healthCheckPort: DEFAULT_HEALTH_CHECK_PORT,
|
|
37
38
|
enablePrometheus: false,
|
|
38
|
-
prometheusPort:
|
|
39
|
+
prometheusPort: DEFAULT_PROMETHEUS_PORT,
|
|
39
40
|
init: () => Promise.resolve(),
|
|
40
41
|
beginTransaction: () => Promise.resolve(),
|
|
41
42
|
endTransaction: (_status) => Promise.resolve()
|
|
@@ -45,46 +46,51 @@ const defaultIndexerConfig = {
|
|
|
45
46
|
* Extends EclesiaEmitter to provide event-driven architecture for modules
|
|
46
47
|
*/
|
|
47
48
|
var EcleciaIndexer = class extends EclesiaEmitter {
|
|
49
|
+
/** Indexer configuration settings */
|
|
50
|
+
config;
|
|
51
|
+
/** Fastify HTTP server for health checks */
|
|
52
|
+
fastify = null;
|
|
53
|
+
/** Prometheus HTTP server instance */
|
|
54
|
+
prometheusServer = null;
|
|
55
|
+
/** Indicates if the indexer has started */
|
|
56
|
+
started = false;
|
|
57
|
+
/** Queue for managing block processing pipeline */
|
|
58
|
+
blockQueue;
|
|
59
|
+
/** Latest block height from the chain */
|
|
60
|
+
latestHeight;
|
|
61
|
+
/** Next block height to process */
|
|
62
|
+
heightToProcess;
|
|
63
|
+
/** Whether the indexer has been initialized */
|
|
64
|
+
initialized = false;
|
|
65
|
+
/** Prometheus metrics server instance */
|
|
66
|
+
prometheus = null;
|
|
67
|
+
/** Number of retry attempts for error recovery */
|
|
68
|
+
retryCount = 0;
|
|
69
|
+
/** CometBFT client for ad-hoc queries */
|
|
70
|
+
client;
|
|
71
|
+
/** CometBFT client for block and validator queries */
|
|
72
|
+
blockClient;
|
|
73
|
+
/** Winston logger instance */
|
|
74
|
+
log;
|
|
75
|
+
/** Flag indicating if indexer should attempt recovery */
|
|
76
|
+
tryToRecover = false;
|
|
77
|
+
/** Health check status for monitoring */
|
|
78
|
+
healthCheck = { status: "CONNECTING" };
|
|
79
|
+
/** WebSocket subscription for new block notifications */
|
|
80
|
+
subscription = null;
|
|
81
|
+
/** Timeout handler for block reception */
|
|
82
|
+
blockTimeout = null;
|
|
48
83
|
/**
|
|
49
84
|
* Creates a new Eclesia indexer instance
|
|
50
85
|
* @param config - Indexer configuration options
|
|
51
86
|
*/
|
|
52
87
|
constructor(config) {
|
|
53
88
|
super();
|
|
54
|
-
this.prometheusServer = null;
|
|
55
|
-
this.initialized = false;
|
|
56
|
-
this.prometheus = null;
|
|
57
|
-
this.retryCount = 0;
|
|
58
|
-
this.tryToRecover = false;
|
|
59
|
-
this.healthCheck = { status: "CONNECTING" };
|
|
60
|
-
this.subscription = null;
|
|
61
|
-
this.blockListener = { next: (data) => {
|
|
62
|
-
this.newBlockReceived(data.header.height);
|
|
63
|
-
} };
|
|
64
|
-
this.asyncEmit = async (type, event) => {
|
|
65
|
-
event.uuid = v4();
|
|
66
|
-
let listenerCount = this.handled.get(type);
|
|
67
|
-
if (!listenerCount) listenerCount = 1;
|
|
68
|
-
let listenersResponded = 0;
|
|
69
|
-
const prom = new Promise((resolve, reject) => {
|
|
70
|
-
const returnFunc = (ev) => {
|
|
71
|
-
if (ev.uuid == event.uuid) if (ev.status) {
|
|
72
|
-
listenersResponded++;
|
|
73
|
-
if (listenersResponded == listenerCount) {
|
|
74
|
-
this.off("uuid", returnFunc);
|
|
75
|
-
resolve();
|
|
76
|
-
}
|
|
77
|
-
} else reject(ev.error);
|
|
78
|
-
};
|
|
79
|
-
this.on("uuid", returnFunc);
|
|
80
|
-
});
|
|
81
|
-
this.emit(type, event);
|
|
82
|
-
return prom;
|
|
83
|
-
};
|
|
84
89
|
validateUrl(config.rpcUrl, "rpcUrl");
|
|
85
90
|
validatePositiveInteger(config.batchSize, "batchSize");
|
|
86
91
|
if (config.genesisPath) validateFilePath(config.genesisPath, "genesisPath");
|
|
87
92
|
if (config.healthCheckPort !== void 0) validatePort(config.healthCheckPort, "healthCheckPort");
|
|
93
|
+
if (config.prometheusPort !== void 0) validatePort(config.prometheusPort, "prometheusPort");
|
|
88
94
|
if (config.startHeight !== void 0) validatePositiveInteger(config.startHeight, "startHeight");
|
|
89
95
|
if (config.pollingInterval !== void 0) validatePositiveInteger(config.pollingInterval, "pollingInterval");
|
|
90
96
|
this.config = {
|
|
@@ -113,6 +119,15 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
113
119
|
};
|
|
114
120
|
if (this.config.minimal) this.blockQueue = new CircularBuffer(this.config.batchSize, queueErrorHandler);
|
|
115
121
|
else this.blockQueue = new CircularBuffer(this.config.batchSize, queueErrorHandler);
|
|
122
|
+
this.on("_unhandled", (msg) => {
|
|
123
|
+
if (msg.uuid) {
|
|
124
|
+
this.log.verbose("Unhandled event: " + msg.type);
|
|
125
|
+
this.emit("uuid", {
|
|
126
|
+
status: true,
|
|
127
|
+
uuid: msg.uuid
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
});
|
|
116
131
|
if (this.config.enablePrometheus) {
|
|
117
132
|
this.prometheus = new IndexerMetrics();
|
|
118
133
|
this.prometheusServer = Fastify({ logger: false });
|
|
@@ -120,12 +135,13 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
120
135
|
res.header("Content-Type", this.prometheus.registry.contentType);
|
|
121
136
|
res.send(await this.prometheus.getMetrics());
|
|
122
137
|
});
|
|
138
|
+
const prometheusPort = this.config.prometheusPort ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);
|
|
123
139
|
this.prometheusServer.listen({
|
|
124
|
-
port:
|
|
140
|
+
port: prometheusPort,
|
|
125
141
|
host: "0.0.0.0"
|
|
126
142
|
}, (err) => {
|
|
127
143
|
if (err) {
|
|
128
|
-
this.log.error(err);
|
|
144
|
+
this.log.error("Prometheus error: " + err);
|
|
129
145
|
this.prometheus?.recordError("metrics_server");
|
|
130
146
|
this.emit("fatal-error", {
|
|
131
147
|
error: err,
|
|
@@ -134,38 +150,34 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
134
150
|
}
|
|
135
151
|
});
|
|
136
152
|
}
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.
|
|
141
|
-
this.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.prometheus?.recordError("health_check_server");
|
|
159
|
-
this.emit("fatal-error", {
|
|
160
|
-
error: err,
|
|
161
|
-
message: "Failed to start health check server"
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
});
|
|
153
|
+
if (this.config.enableHealthcheck) {
|
|
154
|
+
this.fastify = Fastify({ logger: false });
|
|
155
|
+
this.fastify.get("/health", async (_request, reply) => {
|
|
156
|
+
const code = this.healthCheck.status == "OK" ? 200 : 503;
|
|
157
|
+
reply.code(code).send(this.healthCheck);
|
|
158
|
+
});
|
|
159
|
+
const healthPort = this.config.healthCheckPort ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);
|
|
160
|
+
this.fastify.listen({
|
|
161
|
+
port: healthPort,
|
|
162
|
+
host: "0.0.0.0"
|
|
163
|
+
}, (err) => {
|
|
164
|
+
if (err) {
|
|
165
|
+
this.log.error("Health check server error: " + err);
|
|
166
|
+
this.prometheus?.recordError("health_check_server");
|
|
167
|
+
this.emit("fatal-error", {
|
|
168
|
+
error: err,
|
|
169
|
+
message: "Failed to start health check server"
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
165
174
|
}
|
|
166
175
|
setStatus(status) {
|
|
167
176
|
this.healthCheck.status = status;
|
|
168
177
|
}
|
|
178
|
+
blockListener = { next: (data) => {
|
|
179
|
+
this.newBlockReceived(data.header.height);
|
|
180
|
+
} };
|
|
169
181
|
isMinimal(_blockqueue) {
|
|
170
182
|
if (this.config.minimal) return true;
|
|
171
183
|
else return false;
|
|
@@ -184,13 +196,17 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
184
196
|
this.log.info("Connected to RPC for block & validator info");
|
|
185
197
|
return true;
|
|
186
198
|
} catch (error) {
|
|
187
|
-
this.log.error(error);
|
|
199
|
+
this.log.error("RPC connection error: " + error);
|
|
188
200
|
this.prometheus?.recordError("connect_rpc_error");
|
|
189
201
|
this.tryToRecover = true;
|
|
190
202
|
return false;
|
|
191
203
|
}
|
|
192
204
|
}
|
|
205
|
+
stop() {
|
|
206
|
+
this.started = false;
|
|
207
|
+
}
|
|
193
208
|
async start() {
|
|
209
|
+
this.started = true;
|
|
194
210
|
if (this.blockQueue) {
|
|
195
211
|
this.blockQueue.clear();
|
|
196
212
|
this.log.verbose("Starting, clearing block queue");
|
|
@@ -237,6 +253,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
237
253
|
this.setStatus("FAILED");
|
|
238
254
|
throw e;
|
|
239
255
|
}
|
|
256
|
+
this.log.debug("Starting main processing loop");
|
|
240
257
|
this.tryToRecover = false;
|
|
241
258
|
this.fetcher().catch((e) => {
|
|
242
259
|
this.setStatus("FAILED");
|
|
@@ -245,7 +262,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
245
262
|
});
|
|
246
263
|
const hrTime = process.hrtime();
|
|
247
264
|
let ms = hrTime[0] * 1e6 + hrTime[1] / 1e3;
|
|
248
|
-
while (this.blockQueue.size() > 0 && !this.tryToRecover) {
|
|
265
|
+
while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === void 0 || this.heightToProcess <= this.config.endHeight)) {
|
|
249
266
|
if (this.config.enablePrometheus) this.prometheus.updateRetryCount(this.retryCount);
|
|
250
267
|
try {
|
|
251
268
|
if (this.tryToRecover) throw new Error("Exiting processing loop. Attempting to recover indexer");
|
|
@@ -308,7 +325,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
308
325
|
this.log.silly("Committed db tx");
|
|
309
326
|
} catch (e) {
|
|
310
327
|
this.prometheus?.recordError("block_processing_error");
|
|
311
|
-
this.log.error("" + e);
|
|
328
|
+
this.log.error("Block processing error: " + e);
|
|
312
329
|
this.setStatus("FAILED");
|
|
313
330
|
try {
|
|
314
331
|
await this.config.endTransaction(false);
|
|
@@ -323,7 +340,11 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
323
340
|
this.retryCount = 0;
|
|
324
341
|
this.setStatus("OK");
|
|
325
342
|
}
|
|
326
|
-
if (this.
|
|
343
|
+
if (this.config.endHeight !== void 0 && this.heightToProcess >= this.config.endHeight) {
|
|
344
|
+
this.log.info("Reached configured end height. Stopping indexer.");
|
|
345
|
+
this.stop();
|
|
346
|
+
}
|
|
347
|
+
if (this.started) if (this.retryCount < 3) {
|
|
327
348
|
this.log.debug("Indexer retryCount: " + this.retryCount);
|
|
328
349
|
this.log.info("Indexer is restarting");
|
|
329
350
|
setTimeout(() => this.start(), this.retryCount * 5e3);
|
|
@@ -336,12 +357,33 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
336
357
|
});
|
|
337
358
|
}
|
|
338
359
|
}
|
|
360
|
+
asyncEmit = async (type, event) => {
|
|
361
|
+
event.uuid = v4();
|
|
362
|
+
let listenerCount = this.handled.get(type);
|
|
363
|
+
if (!listenerCount) listenerCount = 1;
|
|
364
|
+
let listenersResponded = 0;
|
|
365
|
+
const prom = new Promise((resolve, reject) => {
|
|
366
|
+
const returnFunc = (ev) => {
|
|
367
|
+
if (ev.uuid == event.uuid) if (ev.status) {
|
|
368
|
+
listenersResponded++;
|
|
369
|
+
if (listenersResponded == listenerCount) {
|
|
370
|
+
this.off("uuid", returnFunc);
|
|
371
|
+
resolve();
|
|
372
|
+
}
|
|
373
|
+
} else reject(ev.error);
|
|
374
|
+
};
|
|
375
|
+
this.on("uuid", returnFunc);
|
|
376
|
+
});
|
|
377
|
+
this.emit(type, event);
|
|
378
|
+
return prom;
|
|
379
|
+
};
|
|
339
380
|
async processBlock(block, block_results, validators) {
|
|
340
381
|
let processStart = [0, 0];
|
|
341
382
|
if (this.config.logLevel == "silly") processStart = process.hrtime();
|
|
342
383
|
let endTimer;
|
|
343
384
|
if (this.config.enablePrometheus) endTimer = this.prometheus.timeBlockProcessing();
|
|
344
385
|
const height = block.block.header.height;
|
|
386
|
+
this.heightToProcess = height;
|
|
345
387
|
this.log.debug("Processing block: %d", height);
|
|
346
388
|
const timestamp = toRfc3339WithNanoseconds(block.block.header.time);
|
|
347
389
|
await this.asyncEmit("block", {
|
|
@@ -502,7 +544,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
502
544
|
throw new Error("RPC not responding");
|
|
503
545
|
}
|
|
504
546
|
} catch (e) {
|
|
505
|
-
this.log.error(e);
|
|
547
|
+
this.log.error("Fetching error: " + e);
|
|
506
548
|
break;
|
|
507
549
|
}
|
|
508
550
|
}
|
|
@@ -535,6 +577,10 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
535
577
|
}
|
|
536
578
|
}
|
|
537
579
|
newBlockReceived(height) {
|
|
580
|
+
if (this.blockTimeout) clearTimeout(this.blockTimeout);
|
|
581
|
+
this.blockTimeout = setTimeout(() => {
|
|
582
|
+
this.tryToRecover = true;
|
|
583
|
+
}, 3e4);
|
|
538
584
|
this.log.info("Received new block: %d", height);
|
|
539
585
|
if (height == this.latestHeight) return;
|
|
540
586
|
if (this.blockQueue.synced && !this.tryToRecover) {
|
|
@@ -564,7 +610,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
564
610
|
}));
|
|
565
611
|
}
|
|
566
612
|
} catch (e) {
|
|
567
|
-
this.log.error("" + e);
|
|
613
|
+
this.log.error("New Block Received error: " + e);
|
|
568
614
|
}
|
|
569
615
|
} else this.latestHeight = height;
|
|
570
616
|
}
|
|
@@ -686,4 +732,4 @@ var EcleciaIndexer = class extends EclesiaEmitter {
|
|
|
686
732
|
|
|
687
733
|
//#endregion
|
|
688
734
|
export { EcleciaIndexer, defaultIndexerConfig };
|
|
689
|
-
//# sourceMappingURL=index.
|
|
735
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["timeoutPromise: ReturnType<typeof this.blockQueue.dequeue>","hrTime","uuidv4","processStart: [number, number]","beginBlockEvents: readonly Event[] | readonly Event38[]","endBlockEvents: readonly Event[] | readonly Event38[]","events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }>","eventsToAdd: typeof events","events","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]>","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>"],"sources":["../../src/indexer/index.ts"],"sourcesContent":["/* eslint-disable @stylistic/no-multi-spaces */\n/* eslint-disable max-lines */\nimport {\n createHash,\n} from \"node:crypto\";\nimport * as fs from \"node:fs\";\n\nimport {\n BlockResponse, BlockResultsResponse, CometClient, connectComet, Event, toRfc3339WithNanoseconds,\n} from \"@cosmjs/tendermint-rpc\";\nimport {\n BlockResultsResponse as BlockResultsResponse38, Event as Event38,\n} from \"@cosmjs/tendermint-rpc/build/comet38/responses.js\";\nimport {\n MsgExec,\n} from \"cosmjs-types/cosmos/authz/v1beta1/tx.js\";\nimport {\n QueryValidatorsRequest,\n QueryValidatorsResponse,\n} from \"cosmjs-types/cosmos/staking/v1beta1/query.js\";\nimport {\n Validator,\n} from \"cosmjs-types/cosmos/staking/v1beta1/staking.js\";\nimport {\n Tx,\n} from \"cosmjs-types/cosmos/tx/v1beta1/tx.js\";\nimport Fastify, {\n FastifyInstance,\n} from \"fastify\";\nimport {\n chain,\n} from \"stream-chain\";\nimport Parser from \"stream-json\";\nimport Pick from \"stream-json/filters/Pick.js\";\nimport StreamArray from \"stream-json/streamers/StreamArray.js\";\nimport StreamValues from \"stream-json/streamers/StreamValues.js\";\nimport Batch from \"stream-json/utils/Batch.js\";\nimport {\n v4 as uuidv4,\n} from \"uuid\";\nimport * as winston from \"winston\";\n\nimport {\n DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT,\n GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS,\n} from \"../constants.js\";\nimport {\n EclesiaEmitter,\n} from \"../emitter/index.js\";\nimport {\n IndexerMetrics,\n} from \"../metrics/index.js\";\nimport {\n CircularBuffer,\n} from \"../promise-queue/index.js\";\nimport {\n BlockQueue, EcleciaIndexerConfig, EmitFunc, MinimalBlockQueue,\n UUIDEvent, WithHeightAndUUID,\n} from \"../types/index.js\";\nimport {\n decodeAttr,\n} from \"../utils/index.js\";\nimport {\n validateFilePath, validatePort, validatePositiveInteger, validateUrl,\n} from \"../validation/index.js\";\n\n/** Default configuration for the Eclesia indexer */\nexport const defaultIndexerConfig = {\n startHeight: DEFAULT_START_HEIGHT, // Start indexing from block 1\n batchSize: DEFAULT_BATCH_SIZE, // Process blocks in batches of 500\n modules: [], // No modules enabled by default\n getNextHeight: () => DEFAULT_START_HEIGHT, // Default height retrieval function\n logLevel: \"info\" as EcleciaIndexerConfig[\"logLevel\"], // Default log level\n usePolling: false, // Use WebSocket subscription by default\n pollingInterval: DEFAULT_POLLING_INTERVAL_MS, // Poll every 5 seconds when polling enabled\n shouldProcessGenesis: () => false, // Skip genesis processing by default\n minimal: true, // Use minimal indexing by default\n enableHealthcheck: true, // Enable health check server by default\n healthCheckPort: DEFAULT_HEALTH_CHECK_PORT, // Default health check port\n enablePrometheus: false, // Disable Prometheus metrics server by default\n prometheusPort: DEFAULT_PROMETHEUS_PORT, // Default Prometheus metrics server port\n init: () => Promise.resolve(), // No-op initialization function\n beginTransaction: () => Promise.resolve(), // No-op transaction begin function\n endTransaction: (_status: boolean) => Promise.resolve(), // No-op transaction end function\n};\n\n/**\n * Core blockchain indexer that connects to Tendermint RPC and processes blocks\n * Extends EclesiaEmitter to provide event-driven architecture for modules\n */\nexport class EcleciaIndexer extends EclesiaEmitter {\n /** Indexer configuration settings */\n public config: EcleciaIndexerConfig;\n\n /** Fastify HTTP server for health checks */\n private fastify: FastifyInstance | null = null;\n\n /** Prometheus HTTP server instance */\n private prometheusServer: FastifyInstance | null = null;\n\n /** Indicates if the indexer has started */\n private started: boolean = false;\n\n /** Queue for managing block processing pipeline */\n private blockQueue: BlockQueue;\n\n /** Latest block height from the chain */\n private latestHeight!: number;\n\n /** Next block height to process */\n public heightToProcess!: number;\n\n /** Whether the indexer has been initialized */\n private initialized = false;\n\n /** Prometheus metrics server instance */\n public prometheus: IndexerMetrics | null = null;\n\n /** Number of retry attempts for error recovery */\n private retryCount = 0;\n\n /** CometBFT client for ad-hoc queries */\n public client!: CometClient;\n\n /** CometBFT client for block and validator queries */\n public blockClient!: CometClient;\n\n /** Winston logger instance */\n public log: winston.Logger;\n\n /** Flag indicating if indexer should attempt recovery */\n private tryToRecover: boolean = false;\n\n /** Health check status for monitoring */\n private healthCheck = {\n status: \"CONNECTING\",\n };\n\n /** WebSocket subscription for new block notifications */\n private subscription: ReturnType<CometClient[\"subscribeNewBlock\"]> | null = null;\n\n /** Timeout handler for block reception */\n private blockTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new Eclesia indexer instance\n * @param config - Indexer configuration options\n */\n constructor(config: EcleciaIndexerConfig) {\n super();\n\n // Validate required configuration\n validateUrl(config.rpcUrl, \"rpcUrl\");\n validatePositiveInteger(config.batchSize, \"batchSize\");\n\n // Validate optional genesis path if processing genesis\n if (config.genesisPath) {\n validateFilePath(config.genesisPath, \"genesisPath\");\n }\n\n // Validate health check port if provided\n if (config.healthCheckPort !== undefined) {\n validatePort(config.healthCheckPort, \"healthCheckPort\");\n }\n\n // Validate prometheus port if provided\n if (config.prometheusPort !== undefined) {\n validatePort(config.prometheusPort, \"prometheusPort\");\n }\n\n // Validate start height if provided\n if (config.startHeight !== undefined) {\n validatePositiveInteger(config.startHeight, \"startHeight\");\n }\n\n // Validate polling interval if provided\n if (config.pollingInterval !== undefined) {\n validatePositiveInteger(config.pollingInterval, \"pollingInterval\");\n }\n\n this.config = {\n ...defaultIndexerConfig,\n ...config,\n };\n\n // Initialize logger first so it can be used by queue error handler\n const {\n printf,\n } = winston.format;\n\n const eclesiaFormat = printf(({\n level, message, timestamp,\n }) => {\n return `${timestamp} [${level.toUpperCase()}]:\\t${message}`;\n });\n this.log = winston.createLogger({\n level: this.config.logLevel,\n defaultMeta: {\n service: \"Eclesia Indexer\",\n },\n transports: [\n new winston.transports.File({\n filename: \"error.log\",\n level: \"error\",\n }),\n new winston.transports.File({\n filename: \"combined.log\",\n }),\n new winston.transports.Console({\n format: winston.format.combine(winston.format.splat(),\n winston.format.timestamp(),\n eclesiaFormat,\n winston.format.colorize({\n all: true,\n })),\n }),\n ],\n });\n\n // Initialize block queue based on minimal or full indexing mode\n // Pass error handler that uses the logger\n const queueErrorHandler = (e: unknown) => {\n this.prometheus?.recordError(\"block_queue\");\n this.log.error(\"Error enqueueing block data: \" + e);\n };\n\n if (this.config.minimal) {\n // Minimal mode: only store block and block results\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse]>(this.config.batchSize, queueErrorHandler);\n }\n else {\n // Full mode: also store validator information\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse, Uint8Array]>(this.config.batchSize, queueErrorHandler);\n }\n\n this.on(\"_unhandled\",\n (msg) => {\n if (msg.uuid) {\n this.log.verbose(\"Unhandled event: \" + msg.type);\n this.emit(\"uuid\",\n {\n status: true,\n uuid: msg.uuid,\n });\n }\n });\n if (this.config.enablePrometheus) {\n this.prometheus = new IndexerMetrics();\n this.prometheusServer = Fastify({\n logger: false,\n });\n this.prometheusServer.get(\"/metrics\",\n async (_req, res) => {\n res.header(\"Content-Type\", this.prometheus!.registry.contentType);\n res.send(await this.prometheus!.getMetrics());\n },\n );\n\n const prometheusPort = this.config.prometheusPort\n ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);\n this.prometheusServer.listen({\n port: prometheusPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Prometheus error: \" + err);\n this.prometheus?.recordError(\"metrics_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start metrics server\",\n });\n }\n });\n }\n if (this.config.enableHealthcheck) {\n this.fastify = Fastify({\n logger: false,\n });\n this.fastify.get(\"/health\",\n async (_request, reply) => {\n const code = this.healthCheck.status == \"OK\"\n ? 200\n : 503;\n reply.code(code).send(this.healthCheck);\n });\n const healthPort = this.config.healthCheckPort\n ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);\n this.fastify.listen({\n port: healthPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Health check server error: \" + err);\n this.prometheus?.recordError(\"health_check_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start health check server\",\n });\n }\n });\n }\n }\n\n private setStatus(status: string) {\n this.healthCheck.status = status;\n }\n\n private blockListener = {\n next: (data: {\n header: {\n height: number\n }\n }) => {\n this.newBlockReceived(data.header.height);\n },\n };\n\n private isMinimal(_blockqueue: BlockQueue): _blockqueue is MinimalBlockQueue {\n if (this.config.minimal) {\n return true;\n }\n else {\n return false;\n }\n }\n\n public async connect() {\n try {\n if (this.client && this.tryToRecover) {\n this.log.verbose(\"Recover from error. Attempting to disconnect from RPC\");\n this.client.disconnect();\n this.blockClient.disconnect();\n this.log.verbose(\"Disconnected from RPC\");\n }\n this.client = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for ad hoc queries\");\n\n this.blockClient = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for block & validator info\");\n\n return true;\n }\n catch (error) {\n this.log.error(\"RPC connection error: \" + error);\n this.prometheus?.recordError(\"connect_rpc_error\");\n this.tryToRecover = true;\n return false;\n }\n }\n\n public stop() {\n this.started = false;\n }\n\n public async start() {\n this.started = true;\n if (this.blockQueue) {\n this.blockQueue.clear();\n this.log.verbose(\"Starting, clearing block queue\");\n }\n if (!this.initialized) {\n try {\n if (this.config.init) {\n await this.config.init();\n }\n }\n catch (e) {\n this.log.error(\"Failed to initialize indexer: \" + e);\n\n this.prometheus?.recordError(\"init_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n if (await this.config.shouldProcessGenesis()) {\n try {\n if (this.config.genesisPath) {\n await this.parseGenesis();\n }\n }\n catch (e) {\n this.log.error(\"Failed to parse genesis: \" + e);\n\n this.prometheus?.recordError(\"genesis_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n }\n this.initialized = true;\n }\n try {\n await this.connect();\n if (!this.config.usePolling && this.subscription) {\n this.subscription.removeListener(this.blockListener);\n this.subscription = null;\n this.log.verbose(\"Removed existing block listener and subscription\");\n }\n if (!this.config.usePolling) {\n this.subscription = this.client.subscribeNewBlock\n ? this.client.subscribeNewBlock()\n : null;\n }\n const status = await this.client.status();\n this.latestHeight = status.syncInfo.latestBlockHeight;\n this.log.info(\"Current chain height: \" + this.latestHeight);\n\n this.heightToProcess = await this.config.getNextHeight();\n if (this.config.usePolling) {\n this.pollForBlock();\n }\n else {\n if (this.subscription) {\n this.subscription.addListener(this.blockListener);\n }\n else {\n this.prometheus?.recordError(\"subscription_error\");\n throw new Error(\"Could not subscribe to new blocks\");\n }\n }\n }\n catch (e) {\n this.log.error(\"Failed to set up block listening: \" + e);\n this.prometheus?.recordError(\"block_listening_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n this.log.debug(\"Starting main processing loop\");\n this.tryToRecover = false;\n this.fetcher().catch((e) => {\n this.setStatus(\"FAILED\");\n\n this.prometheus?.recordError(\"fetching_error\");\n throw new Error(\"Error in fetching service: \" + e);\n });\n\n const hrTime = process.hrtime();\n let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === undefined || this.heightToProcess <= this.config.endHeight)) {\n if (this.config.enablePrometheus) {\n this.prometheus!.updateRetryCount(this.retryCount);\n }\n // await the dequeued promise is essentially awaiting fetched data for that block\n try {\n if (this.tryToRecover) {\n throw new Error(\"Exiting processing loop. Attempting to recover indexer\");\n }\n // Index block inside a db transaction to ensure data consistency\n await this.config.beginTransaction();\n this.log.silly(\"Started db tx\");\n let height, timestamp;\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1]);\n }\n else {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n\n this.log.silly(\"Decoded block\");\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1],\n QueryValidatorsResponse.decode(toProcess[2]).validators);\n }\n // Emit events to trigger periodic operations every 50, 100 and 1000 blocks\n if (height % PERIODIC_INTERVALS.LARGE == 0) {\n const hrTime = process.hrtime();\n const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n const duration = newms - ms;\n ms = newms;\n const rate = 1000000000 / duration;\n this.log.info(\"Processing:\" + rate.toFixed(2) + \"blocks/sec\");\n await this.asyncEmit(\"periodic/1000\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.MEDIUM == 0) {\n await this.asyncEmit(\"periodic/100\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.SMALL == 0) {\n await this.asyncEmit(\"periodic/50\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n this.log.silly(\"Handled periodic events\");\n\n await this.config.endTransaction(true);\n\n this.log.silly(\"Committed db tx\");\n }\n catch (e) {\n this.prometheus?.recordError(\"block_processing_error\");\n this.log.error(\"Block processing error: \" + e);\n this.setStatus(\"FAILED\");\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.tryToRecover = true;\n this.retryCount++;\n break;\n }\n this.retryCount = 0;\n this.setStatus(\"OK\");\n }\n if (this.config.endHeight !== undefined && this.heightToProcess >= this.config.endHeight!) {\n this.log.info(\"Reached configured end height. Stopping indexer.\");\n this.stop();\n }\n if (this.started) {\n if (this.retryCount < 3) {\n this.log.debug(\"Indexer retryCount: \" + this.retryCount);\n this.log.info(\"Indexer is restarting\");\n setTimeout(() => this.start(),\n this.retryCount * 5000);\n }\n else {\n this.log.info(\"Indexer failed too many times. Exiting.\");\n this.emit(\"fatal-error\", {\n error: new Error(\"Max retry attempts exceeded\"),\n message: \"Indexer failed too many times\",\n retryCount: this.retryCount,\n });\n }\n }\n }\n\n public asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>> = async (\n type,\n event,\n ) => {\n event.uuid = uuidv4();\n\n /*\n * More than 1 listener can be registered for an event type\n * Fortunately these are all set up during module init() so we have a consistent count\n * so we can count responses to resolve when complete\n * values are irrelevant as promise resolution is only used for flow control\n */\n let listenerCount = this.handled.get(type);\n if (!listenerCount) {\n // Setting listenerCount to 1 (the unhandled listener)\n listenerCount = 1;\n }\n let listenersResponded = 0;\n const prom = new Promise<void>((resolve, reject) => {\n const returnFunc = (ev: UUIDEvent) => {\n if (ev.uuid == event.uuid) {\n if (ev.status) {\n listenersResponded++;\n if (listenersResponded == listenerCount) {\n // All listeners have done their thing so we can remove listener, resolve and continue execution\n this.off(\"uuid\",\n returnFunc);\n resolve();\n }\n }\n else {\n // At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location\n reject(ev.error);\n }\n }\n };\n this.on(\"uuid\",\n returnFunc);\n });\n this.emit(type,\n event);\n\n return prom;\n };\n\n private async processBlock(block: BlockResponse, block_results: BlockResultsResponse | BlockResultsResponse38, validators?: Validator[]) {\n let processStart: [number, number] = [0, 0];\n if (this.config.logLevel == \"silly\") {\n processStart = process.hrtime();\n }\n let endTimer;\n if (this.config.enablePrometheus) {\n endTimer = this.prometheus!.timeBlockProcessing();\n }\n const height = block.block.header.height;\n this.heightToProcess = height;\n this.log.debug(\"Processing block: %d\",\n height);\n // Initialize height & timestamp to be used for this block-processing run\n const timestamp = toRfc3339WithNanoseconds(block.block.header.time);\n\n // Use & await asyncEmit to ensure db insertions in order\n\n /*\n * Emit block information to any interested modules.\n * Primarily the required block module listens to this\n */\n await this.asyncEmit(\"block\",\n {\n value: {\n block,\n block_results,\n },\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled block event\");\n\n let beginBlockEvents: readonly Event[] | readonly Event38[];\n let endBlockEvents: readonly Event[] | readonly Event38[];\n if ((block_results as BlockResultsResponse38).finalizeBlockEvents) {\n beginBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"begin_block\")) as readonly Event38[];\n endBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"end_block\")) as readonly Event38[];\n }\n else {\n beginBlockEvents = (block_results as BlockResultsResponse).beginBlockEvents;\n endBlockEvents = (block_results as BlockResultsResponse).endBlockEvents;\n }\n // Deal with begin_block events first\n await this.asyncEmit(\"begin_block\",\n {\n value: {\n events: beginBlockEvents!,\n validators,\n },\n height,\n timestamp,\n });\n\n this.log.silly(\"Modules handled begin_block events\");\n\n // Then individual tx_events\n await this.asyncEmit(\"tx_events\",\n {\n value: block_results.results,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled tx events\");\n\n // Emit details and result for each tx msg separately\n for (let t = 0; t < block.block.txs.length; t++) {\n const tx = Tx.decode(block.block.txs[t]);\n\n const result = block_results.results[t].code;\n const txlog = block_results.results[t].log;\n\n if (result != 0) {\n // Tx failed. Ignore\n continue;\n }\n if (tx.body && tx.body.memo != \"\") {\n const txHash = createHash(\"sha256\").update(block.block.txs[t])\n .digest(\"hex\");\n await this.asyncEmit(\"tx_memo\",\n {\n value: {\n txHash,\n txBody: tx.body,\n },\n height,\n timestamp,\n });\n }\n // parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg\n let events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }> = txlog\n ? JSON.parse(txlog)\n : [];\n if (events.length == 0) {\n const eventsToAdd: typeof events = [];\n this.log.silly(\"No events found in tx log. Parsing events for msg_index\");\n for (let m = 0; m < block_results.results[t].events.length; m++) {\n if (block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")) {\n const mi = decodeAttr(block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")?.value ?? \"\");\n if (mi != \"\") {\n const miNum = parseInt(mi);\n let ev = eventsToAdd.find(x => x.msg_index == miNum);\n if (!ev) {\n ev = {\n msg_index: miNum,\n events: [block_results.results[t].events[m]],\n };\n eventsToAdd.push(ev);\n }\n else {\n ev.events.push(block_results.results[t].events[m] as Event);\n }\n }\n }\n }\n events = events.concat(eventsToAdd);\n }\n const msgs = tx.body?.messages;\n\n if (msgs) {\n for (let i = 0; i < msgs.length; i++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + msgs[i].typeUrl);\n const msgevents\n = msgs.length > 1\n ? events.find(x => x.msg_index == i)?.events\n : events[0].events;\n await this.asyncEmit(msgs[i].typeUrl as never,\n {\n value: {\n tx: msgs[i].value as never,\n events: msgevents,\n } as never,\n height,\n timestamp,\n });\n if (msgs[i].typeUrl == \"/cosmos.authz.v1beta1.MsgExec\") {\n const authzMsgs = MsgExec.decode(msgs[i].value).msgs;\n if (authzMsgs) {\n for (let r = 0; r < authzMsgs.length; r++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + authzMsgs[r].typeUrl);\n const authzMsgEvents = msgevents?.reduce((events, evt) => {\n if (evt.attributes.filter(x => decodeAttr(x.key) == \"authz_msg_index\" && decodeAttr(x.value) == \"\" + r).length > 0) {\n events.push(evt);\n }\n return events;\n },\n [] as (Event | Event38)[]);\n await this.asyncEmit(authzMsgs[r].typeUrl as never,\n {\n value: {\n tx: authzMsgs[r].value as never,\n events: authzMsgEvents,\n } as never,\n height,\n timestamp,\n });\n }\n }\n }\n }\n }\n }\n this.log.silly(\"Modules handled msg events\");\n if (this.config.enablePrometheus) {\n this.prometheus!.recordTransactions(block.block.txs.length);\n }\n // Then deal with end_block events\n await this.asyncEmit(\"end_block\",\n {\n value: endBlockEvents!,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled end_block events\");\n if (this.config.logLevel == \"silly\") {\n const processEnd = process.hrtime(processStart);\n const processTime = processEnd[0] * 1000 + processEnd[1] / 1000000;\n this.log.silly(\"Processed block %d in %d ms\",\n height,\n processTime.toFixed(2));\n }\n\n if (this.config.enablePrometheus) {\n endTimer!();\n }\n if (this.config.enablePrometheus) {\n this.prometheus!.updateBlockMetrics(height, this.latestHeight, this.blockQueue.size());\n }\n }\n\n private async fetcher() {\n for (let i = this.heightToProcess; i <= this.latestHeight; i++) {\n this.log.debug(\"Fetching: \" + i);\n if (this.tryToRecover) {\n this.log.verbose(\"Exiting fetcher loop. Attempting to recover indexer\");\n break;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const toIndex = Promise.race([Promise.all([this.blockClient.block(i) as Promise<BlockResponse>, this.blockClient.blockResults(i) as Promise<BlockResultsResponse>]), timeoutPromise]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>;\n this.blockQueue.enqueue(toIndex);\n }\n else {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: PAGINATION_LIMITS.VALIDATORS,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n const toIndex = Promise.race([\n Promise.all([\n this.blockClient.block(i) as Promise<BlockResponse>,\n this.blockClient.blockResults(i) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n i,\n false),\n ]),\n timeoutPromise,\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>;\n this.blockQueue.enqueue(toIndex);\n }\n await this.blockQueue.continue();\n if (this.tryToRecover) {\n this.retryCount++;\n throw new Error(\"RPC not responding\");\n }\n }\n catch (e) {\n this.log.error(\"Fetching error: \" + e);\n break;\n }\n }\n if (!this.tryToRecover) {\n this.blockQueue.setSynced();\n this.log.info(\"Synced to latest height\");\n }\n }\n\n public async callABCI(path: string, data: Uint8Array, height?: number, adHoc: boolean = true): Promise<Uint8Array> {\n try {\n const endTimer = this.prometheus?.timeRpcCall(path) ?? void 0;\n const abciq = await\n (adHoc\n ? this.client\n : this.blockClient).abciQuery({\n path,\n data,\n height: height,\n });\n endTimer?.();\n if (abciq) {\n return abciq.value;\n }\n else {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.prometheus?.recordError(\"abci_query_error\");\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n catch (_e) {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.retryCount++;\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n\n private newBlockReceived(height: number): void {\n if (this.blockTimeout) {\n clearTimeout(this.blockTimeout);\n }\n this.blockTimeout = setTimeout(() => {\n this.tryToRecover = true;\n }, 30000);\n this.log.info(\"Received new block: %d\",\n height);\n if (height == this.latestHeight) {\n return;\n }\n // If we are synced, add to end of queue\n if (this.blockQueue.synced && !this.tryToRecover) {\n this.latestHeight = height;\n if (this.blockQueue.size() + 1 == this.config.batchSize) {\n this.prometheus?.recordError(\"block_queue_full\");\n this.log.error(\"Block queue is full. Cannot add new block\");\n this.tryToRecover = true;\n this.retryCount++;\n return;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n this.blockQueue.enqueue(Promise.all([this.client.block(height) as Promise<BlockResponse>, this.client.blockResults(height) as Promise<BlockResultsResponse>]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>);\n }\n else {\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: 1000n,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n this.blockQueue.enqueue(Promise.all([\n this.client.block(height) as Promise<BlockResponse>,\n this.client.blockResults(height) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n height,\n false),\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>);\n }\n }\n catch (e) {\n this.log.error(\"New Block Received error: \" + e);\n }\n }\n else {\n this.latestHeight = height;\n }\n }\n\n private async pollForBlock() {\n try {\n const status = await this.client.status();\n if (status.syncInfo.latestBlockHeight > this.latestHeight) {\n while (this.latestHeight < status.syncInfo.latestBlockHeight) {\n this.newBlockReceived(this.latestHeight + 1);\n }\n }\n setTimeout(() => {\n this.pollForBlock();\n },\n this.config.pollingInterval);\n }\n catch (e) {\n this.log.error(\"Error polling for new block: \" + e);\n this.tryToRecover = true;\n this.retryCount++;\n }\n }\n\n private readGenesis(): Parser.Parser {\n if (this.config.genesisPath) {\n return fs.createReadStream(this.config.genesisPath).pipe(Parser.parser());\n }\n else {\n throw new Error(\"Genesis path not set\");\n }\n }\n\n private async setArrayReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n let counter = 0;\n let chunkCounter = 0;\n\n // Wrapper processor that handles transaction chunking\n const chunkProcessor = async (data: unknown) => {\n chunkCounter++;\n this.log.debug(`Processing genesis chunk ${chunkCounter}`);\n\n await processor(data);\n\n // Commit and restart transaction every 5 chunks (5000 entries)\n // This prevents timeout on large genesis files\n if (chunkCounter % 5 === 0) {\n this.log.debug(`Committing transaction after chunk ${chunkCounter}`);\n await this.config.endTransaction(true);\n await this.config.beginTransaction();\n }\n };\n\n chain([\n this.readGenesis(),\n ...pickers,\n StreamArray.streamArray(),\n Batch.batch({\n batchSize: GENESIS_BATCH_SIZE,\n }),\n chunkProcessor,\n ])\n .on(\"data\",\n (data) => {\n if (data && Array.isArray(data)) {\n counter = counter + data.length;\n }\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries in ${chunkCounter} chunks`);\n resolve(true);\n });\n }\n catch (_e) {\n this.log.verbose(\"Error in setArrayReader: \" + _e);\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async setValueReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n\n let counter = 0;\n chain([this.readGenesis(), ...pickers, StreamValues.streamValues(), processor])\n .on(\"data\",\n (_data) => {\n counter++;\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries`);\n resolve(true);\n });\n }\n catch (_e) {\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async parseGenesis() {\n this.log.info(\"Parsing genesis\");\n await this.config.beginTransaction();\n try {\n this.log.info(\"Starting genesis import\");\n this.log.debug(\"Importing genesis file...\");\n\n for (const [key, _value] of this.handled) {\n if (key.startsWith(\"genesis/\")) {\n const genesisEntry = key.split(\"/\");\n\n this.log.verbose(\"Importing \" + key + \"...\");\n if (genesisEntry[1] == \"array\") {\n await this.setArrayReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.map((x: {\n value: never\n }) => x.value),\n } as never);\n return data;\n });\n }\n else {\n await this.setValueReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.value,\n } as never);\n return data;\n });\n }\n }\n }\n\n this.log.info(\"Importing gen TXs...\");\n\n await this.setArrayReader(\"app_state.genutil.gen_txs\",\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n for (let j = 0; j < data.length; j++) {\n const gentx = data[j].value;\n for (let i = 0; i < gentx.body.messages.length; i++) {\n const msg = gentx.body.messages[i];\n await this.asyncEmit((\"gentx\" + msg[\"@type\"]) as never,\n {\n value: msg,\n } as never);\n }\n }\n return data;\n });\n await this.config.endTransaction(true);\n\n this.log.info(\"Finished importing\");\n }\n catch (e) {\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database_error\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.log.error(\"Failed to import genesis\");\n throw e;\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/metrics/index.cjs
CHANGED
|
@@ -8,6 +8,34 @@ let prom_client = require("prom-client");
|
|
|
8
8
|
*/
|
|
9
9
|
/** Prometheus metrics registry */
|
|
10
10
|
var IndexerMetrics = class {
|
|
11
|
+
/** Prometheus registry instance */
|
|
12
|
+
registry;
|
|
13
|
+
/** Counter for total blocks indexed */
|
|
14
|
+
blocksIndexed;
|
|
15
|
+
/** Gauge for current block height */
|
|
16
|
+
currentHeight;
|
|
17
|
+
/** Gauge for latest chain block height */
|
|
18
|
+
latestHeight;
|
|
19
|
+
/** Gauge for blocks behind chain tip */
|
|
20
|
+
blocksBehind;
|
|
21
|
+
/** Gauge for block queue depth */
|
|
22
|
+
queueDepth;
|
|
23
|
+
/** Counter for total errors */
|
|
24
|
+
errors;
|
|
25
|
+
/** Counter for RPC errors */
|
|
26
|
+
rpcErrors;
|
|
27
|
+
/** Counter for database errors */
|
|
28
|
+
databaseErrors;
|
|
29
|
+
/** Histogram for block processing duration */
|
|
30
|
+
blockProcessingDuration;
|
|
31
|
+
/** Histogram for RPC call duration */
|
|
32
|
+
rpcCallDuration;
|
|
33
|
+
/** Histogram for database query duration */
|
|
34
|
+
databaseQueryDuration;
|
|
35
|
+
/** Gauge for retry count */
|
|
36
|
+
retryCount;
|
|
37
|
+
/** Counter for total transactions processed */
|
|
38
|
+
transactionsProcessed;
|
|
11
39
|
constructor() {
|
|
12
40
|
this.registry = new prom_client.Registry();
|
|
13
41
|
(0, prom_client.collectDefaultMetrics)({ register: this.registry });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Registry","Counter","Gauge","Histogram"],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Registry","Counter","Gauge","Histogram"],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGK,SAAA,aAAA,EAlBD,KAkBC;EAGS;EAGR,SAAA,YAAA,EArBH,KAqBG;EAGM;EAGX,SAAA,YAAA,EAxBE,KAwBF;EAGW;EA8IpB,SAAA,UAAA,EAtKS,KAsKT;EAAA;EAoBO,SAAA,MAAA,EAvLF,OAuLE;EAAA;EAsBS,SAAA,SAAA,EA1MR,OA0MQ;EAAA;EAwCf,SAAA,cAAA,EA/OY,OA+OZ;EAAO;oCA5Oc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCA8IpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGK,SAAA,aAAA,EAlBD,KAkBC;EAGS;EAGR,SAAA,YAAA,EArBH,KAqBG;EAGM;EAGX,SAAA,YAAA,EAxBE,KAwBF;EAGW;EA8IpB,SAAA,UAAA,EAtKS,KAsKT;EAAA;EAoBO,SAAA,MAAA,EAvLF,OAuLE;EAAA;EAsBS,SAAA,SAAA,EA1MR,OA0MQ;EAAA;EAwCf,SAAA,cAAA,EA/OY,OA+OZ;EAAO;oCA5Oc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCA8IpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
|