@apibara/indexer 2.1.0-beta.40 → 2.1.0-beta.42
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/index.cjs +60 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +60 -23
- package/dist/index.mjs.map +1 -1
- package/dist/internal/plugins.d.cts +1 -1
- package/dist/internal/plugins.d.mts +1 -1
- package/dist/internal/plugins.d.ts +1 -1
- package/dist/internal/testing.cjs +14 -8
- package/dist/internal/testing.cjs.map +1 -1
- package/dist/internal/testing.d.cts +12 -10
- package/dist/internal/testing.d.mts +12 -10
- package/dist/internal/testing.d.ts +12 -10
- package/dist/internal/testing.mjs +14 -8
- package/dist/internal/testing.mjs.map +1 -1
- package/dist/plugins/index.d.cts +2 -2
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/index.d.ts +2 -2
- package/dist/shared/{indexer.806c605c.d.cts → indexer.4ef52548.d.cts} +29 -11
- package/dist/shared/{indexer.806c605c.d.mts → indexer.4ef52548.d.mts} +29 -11
- package/dist/shared/{indexer.806c605c.d.ts → indexer.4ef52548.d.ts} +29 -11
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.mts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/vcr/index.d.cts +1 -1
- package/dist/vcr/index.d.mts +1 -1
- package/dist/vcr/index.d.ts +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/indexer.ts +77 -26
- package/src/internal/testing.ts +39 -18
- package/src/utils/index.ts +21 -0
package/dist/index.cjs
CHANGED
|
@@ -68,6 +68,24 @@ function createIndexerMetrics() {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
function reloadIndexer() {
|
|
72
|
+
const context = config.useIndexerContext();
|
|
73
|
+
context._reload = true;
|
|
74
|
+
}
|
|
75
|
+
function reloadIfNeeded() {
|
|
76
|
+
const context = config.useIndexerContext();
|
|
77
|
+
if (context._reload) {
|
|
78
|
+
context._reload = false;
|
|
79
|
+
throw new ReloadIndexerRequest();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
class ReloadIndexerRequest extends Error {
|
|
83
|
+
constructor(message) {
|
|
84
|
+
super(message);
|
|
85
|
+
this.name = "ReloadIndexerRequest";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
71
89
|
function defineIndexer(streamConfig) {
|
|
72
90
|
return (config) => ({
|
|
73
91
|
streamConfig,
|
|
@@ -97,17 +115,21 @@ async function runWithReconnect(client, indexer, options = {}) {
|
|
|
97
115
|
const maxRetries = options.maxRetries ?? 10;
|
|
98
116
|
const retryDelay = options.retryDelay ?? 1e3;
|
|
99
117
|
const maxWait = options.maxWait ?? 3e4;
|
|
100
|
-
const runOptions = {
|
|
101
|
-
onConnect() {
|
|
102
|
-
retryCount = 0;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
118
|
while (true) {
|
|
119
|
+
const abortController = new AbortController();
|
|
120
|
+
const runOptions = {
|
|
121
|
+
onConnect() {
|
|
122
|
+
retryCount = 0;
|
|
123
|
+
},
|
|
124
|
+
abortSignal: abortController.signal
|
|
125
|
+
};
|
|
106
126
|
try {
|
|
107
127
|
await run(client, indexer, runOptions);
|
|
128
|
+
abortController.abort();
|
|
108
129
|
return;
|
|
109
130
|
} catch (error) {
|
|
110
131
|
retryCount++;
|
|
132
|
+
abortController.abort();
|
|
111
133
|
if (error instanceof protocol.ClientError || error instanceof protocol.ServerError) {
|
|
112
134
|
const isServerError = error instanceof protocol.ServerError;
|
|
113
135
|
if (error.code === protocol.Status.INTERNAL) {
|
|
@@ -135,11 +157,12 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
135
157
|
if (indexer.options.debug) {
|
|
136
158
|
context.debug = true;
|
|
137
159
|
}
|
|
138
|
-
|
|
139
|
-
|
|
160
|
+
const { abortSignal } = runOptions;
|
|
161
|
+
await indexer.hooks.callHook("plugins:init", { abortSignal });
|
|
162
|
+
const middleware = await registerMiddleware(indexer, abortSignal);
|
|
140
163
|
const indexerMetrics = createIndexerMetrics();
|
|
141
164
|
const tracer = createTracer();
|
|
142
|
-
await indexer.hooks.callHook("run:before");
|
|
165
|
+
await indexer.hooks.callHook("run:before", { abortSignal });
|
|
143
166
|
const { indexerName: indexerId } = internal_plugins.useInternalContext();
|
|
144
167
|
const isFactoryMode = indexer.options.factory !== void 0;
|
|
145
168
|
let startingCursor;
|
|
@@ -160,13 +183,17 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
160
183
|
startingCursor
|
|
161
184
|
};
|
|
162
185
|
const options = {};
|
|
163
|
-
await indexer.hooks.callHook("connect:before", {
|
|
186
|
+
await indexer.hooks.callHook("connect:before", {
|
|
187
|
+
request,
|
|
188
|
+
options,
|
|
189
|
+
abortSignal
|
|
190
|
+
});
|
|
164
191
|
let mainFilter;
|
|
165
192
|
if (isFactoryMode) {
|
|
166
193
|
mainFilter = request.filter[1];
|
|
167
194
|
}
|
|
168
195
|
let stream = client.streamData(request, options)[Symbol.asyncIterator]();
|
|
169
|
-
await indexer.hooks.callHook("connect:after", { request });
|
|
196
|
+
await indexer.hooks.callHook("connect:after", { request, abortSignal });
|
|
170
197
|
let onConnectCalled = false;
|
|
171
198
|
while (true) {
|
|
172
199
|
const { value: message, done } = await stream.next();
|
|
@@ -179,7 +206,7 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
179
206
|
await runOptions.onConnect();
|
|
180
207
|
}
|
|
181
208
|
}
|
|
182
|
-
await indexer.hooks.callHook("message", { message });
|
|
209
|
+
await indexer.hooks.callHook("message", { message, abortSignal });
|
|
183
210
|
switch (message._tag) {
|
|
184
211
|
case "data": {
|
|
185
212
|
await tracer.startActiveSpan("message data", async (span) => {
|
|
@@ -194,6 +221,7 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
194
221
|
indexer_id: indexerId
|
|
195
222
|
}
|
|
196
223
|
);
|
|
224
|
+
reloadIfNeeded();
|
|
197
225
|
await middleware(context, async () => {
|
|
198
226
|
let block;
|
|
199
227
|
if (isFactoryMode && finality !== "pending") {
|
|
@@ -207,7 +235,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
207
235
|
endCursor,
|
|
208
236
|
finality,
|
|
209
237
|
production,
|
|
210
|
-
context
|
|
238
|
+
context,
|
|
239
|
+
abortSignal
|
|
211
240
|
});
|
|
212
241
|
if (filter) {
|
|
213
242
|
mainFilter = indexer.streamConfig.mergeFilter(
|
|
@@ -221,7 +250,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
221
250
|
};
|
|
222
251
|
await indexer.hooks.callHook("connect:factory", {
|
|
223
252
|
request: request2,
|
|
224
|
-
endCursor
|
|
253
|
+
endCursor,
|
|
254
|
+
abortSignal
|
|
225
255
|
});
|
|
226
256
|
stream = client.streamData(request2, options)[Symbol.asyncIterator]();
|
|
227
257
|
const { value: message2 } = await stream.next();
|
|
@@ -241,12 +271,14 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
241
271
|
endCursor,
|
|
242
272
|
finality,
|
|
243
273
|
production,
|
|
244
|
-
context
|
|
274
|
+
context,
|
|
275
|
+
abortSignal
|
|
245
276
|
});
|
|
246
277
|
span2.end();
|
|
247
278
|
});
|
|
248
279
|
}
|
|
249
280
|
});
|
|
281
|
+
reloadIfNeeded();
|
|
250
282
|
span.end();
|
|
251
283
|
});
|
|
252
284
|
indexerMetrics.processedBlockCounter.add(1, {
|
|
@@ -263,7 +295,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
263
295
|
indexer_id: indexerId
|
|
264
296
|
});
|
|
265
297
|
await indexer.hooks.callHook("message:invalidate", {
|
|
266
|
-
message: message.invalidate
|
|
298
|
+
message: message.invalidate,
|
|
299
|
+
abortSignal
|
|
267
300
|
});
|
|
268
301
|
span.end();
|
|
269
302
|
});
|
|
@@ -272,7 +305,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
272
305
|
case "finalize": {
|
|
273
306
|
await tracer.startActiveSpan("message finalize", async (span) => {
|
|
274
307
|
await indexer.hooks.callHook("message:finalize", {
|
|
275
|
-
message: message.finalize
|
|
308
|
+
message: message.finalize,
|
|
309
|
+
abortSignal
|
|
276
310
|
});
|
|
277
311
|
span.end();
|
|
278
312
|
});
|
|
@@ -280,7 +314,9 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
280
314
|
}
|
|
281
315
|
case "heartbeat": {
|
|
282
316
|
await tracer.startActiveSpan("message heartbeat", async (span) => {
|
|
283
|
-
|
|
317
|
+
reloadIfNeeded();
|
|
318
|
+
await indexer.hooks.callHook("message:heartbeat", { abortSignal });
|
|
319
|
+
reloadIfNeeded();
|
|
284
320
|
span.end();
|
|
285
321
|
});
|
|
286
322
|
break;
|
|
@@ -300,7 +336,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
300
336
|
}
|
|
301
337
|
}
|
|
302
338
|
await indexer.hooks.callHook("message:systemMessage", {
|
|
303
|
-
message: message.systemMessage
|
|
339
|
+
message: message.systemMessage,
|
|
340
|
+
abortSignal
|
|
304
341
|
});
|
|
305
342
|
span.end();
|
|
306
343
|
}
|
|
@@ -312,16 +349,16 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
312
349
|
throw new Error("not implemented");
|
|
313
350
|
}
|
|
314
351
|
}
|
|
315
|
-
await indexer.hooks.callHook("run:after");
|
|
316
352
|
}
|
|
353
|
+
await indexer.hooks.callHook("run:after", { abortSignal });
|
|
317
354
|
});
|
|
318
355
|
}
|
|
319
|
-
async function registerMiddleware(indexer) {
|
|
356
|
+
async function registerMiddleware(indexer, abortSignal) {
|
|
320
357
|
const middleware = [];
|
|
321
358
|
const use = (fn) => {
|
|
322
359
|
middleware.push(fn);
|
|
323
360
|
};
|
|
324
|
-
await indexer.hooks.callHook("handler:middleware", { use });
|
|
361
|
+
await indexer.hooks.callHook("handler:middleware", { use, abortSignal });
|
|
325
362
|
const composed = compose(middleware);
|
|
326
363
|
return async function _composedIndexerMiddleware(context, next) {
|
|
327
364
|
await composed(context, next);
|
|
@@ -329,8 +366,10 @@ async function registerMiddleware(indexer) {
|
|
|
329
366
|
}
|
|
330
367
|
|
|
331
368
|
exports.useIndexerContext = config.useIndexerContext;
|
|
369
|
+
exports.ReloadIndexerRequest = ReloadIndexerRequest;
|
|
332
370
|
exports.createIndexer = createIndexer;
|
|
333
371
|
exports.defineIndexer = defineIndexer;
|
|
372
|
+
exports.reloadIndexer = reloadIndexer;
|
|
334
373
|
exports.run = run;
|
|
335
374
|
exports.runWithReconnect = runWithReconnect;
|
|
336
375
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/compose.ts","../src/otel.ts","../src/indexer.ts"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2021 - present, Yusuke Wada and Hono contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { IndexerContext } from \"./context\";\n\nexport type NextFunction = () => Promise<void>;\nexport type MiddlewareFunction<C> = (\n context: C,\n next: NextFunction,\n) => Promise<void>;\n\nexport function compose<C extends IndexerContext>(\n middleware: MiddlewareFunction<C>[],\n): (context: C, next?: NextFunction) => Promise<void> {\n return (context, next) => {\n let index = -1;\n\n return dispatch(0);\n\n /// Dispatch the middleware functions.\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n let handler: MiddlewareFunction<C> | undefined;\n\n if (i >= middleware.length) {\n if (next) {\n await next();\n }\n\n return;\n }\n\n if (middleware[i]) {\n handler = middleware[i];\n } else {\n handler = i === middleware.length ? next : undefined;\n }\n\n if (!handler) {\n throw new Error(\"Handler not found\");\n }\n\n await handler(context, () => dispatch(i + 1));\n }\n };\n}\n","import { metrics, trace } from \"@opentelemetry/api\";\n\nexport function createTracer() {\n return trace.getTracer(\"@apibara/indexer\");\n}\n\nexport function createIndexerMetrics() {\n const meter = metrics.getMeter(\"@apibara/indexer\");\n\n const currentBlockGauge = meter.createGauge(\"current_block\", {\n description: \"Current block number being processed\",\n unit: \"{block}\",\n });\n\n const processedBlockCounter = meter.createCounter(\"processed_blocks\", {\n description: \"Number of blocks processed\",\n unit: \"{blocks}\",\n });\n\n const reorgCounter = meter.createCounter(\"reorgs\", {\n description: \"Number of reorgs (invalidate messages) received\",\n unit: \"{reorgs}\",\n });\n\n return {\n currentBlockGauge,\n processedBlockCounter,\n reorgCounter,\n };\n}\n","import {\n type Client,\n ClientError,\n type CreateClientOptions,\n type Cursor,\n type DataFinality,\n type DataProduction,\n type Finalize,\n type Invalidate,\n ServerError,\n Status,\n type StreamConfig,\n type StreamDataOptions,\n type StreamDataRequest,\n type StreamDataResponse,\n type SystemMessage,\n} from \"@apibara/protocol\";\nimport consola from \"consola\";\nimport {\n type Hookable,\n type NestedHooks,\n createDebugger,\n createHooks,\n} from \"hookable\";\n\nimport assert from \"node:assert\";\nimport { type MiddlewareFunction, type NextFunction, compose } from \"./compose\";\nimport {\n type IndexerContext,\n indexerAsyncContext,\n useIndexerContext,\n} from \"./context\";\nimport { createIndexerMetrics, createTracer } from \"./otel\";\nimport type { IndexerPlugin } from \"./plugins\";\nimport { useInternalContext } from \"./plugins/context\";\n\nexport type UseMiddlewareFunction = (\n fn: MiddlewareFunction<IndexerContext>,\n) => void;\n\nexport interface IndexerHooks<TFilter, TBlock> {\n \"plugins:init\": () => void;\n \"run:before\": () => void;\n \"run:after\": () => void;\n \"connect:before\": ({\n request,\n options,\n }: {\n request: StreamDataRequest<TFilter>;\n options: StreamDataOptions;\n }) => void;\n \"connect:after\": ({\n request,\n }: {\n request: StreamDataRequest<TFilter>;\n }) => void;\n \"connect:factory\": ({\n request,\n endCursor,\n }: {\n request: StreamDataRequest<TFilter>;\n endCursor?: Cursor;\n }) => void;\n \"handler:middleware\": ({ use }: { use: UseMiddlewareFunction }) => void;\n message: ({ message }: { message: StreamDataResponse<TBlock> }) => void;\n \"message:invalidate\": ({ message }: { message: Invalidate }) => void;\n \"message:finalize\": ({ message }: { message: Finalize }) => void;\n \"message:heartbeat\": () => void;\n \"message:systemMessage\": ({ message }: { message: SystemMessage }) => void;\n}\n\nexport type IndexerStartingCursor =\n | {\n startingCursor?: never;\n startingBlock: bigint;\n }\n | {\n startingCursor: Cursor;\n startingBlock?: never;\n }\n | {\n startingCursor?: never;\n startingBlock?: never;\n };\n\nexport type HandlerArgs<TBlock> = {\n block: TBlock;\n cursor?: Cursor | undefined;\n endCursor?: Cursor | undefined;\n finality: DataFinality;\n production: DataProduction;\n context: IndexerContext;\n};\n\nexport type IndexerConfig<TFilter, TBlock> = {\n streamUrl: string;\n filter: TFilter;\n finality?: DataFinality;\n clientOptions?: CreateClientOptions;\n factory?: (args: HandlerArgs<TBlock>) => Promise<{\n filter?: TFilter;\n }>;\n transform: (args: HandlerArgs<TBlock>) => Promise<void>;\n hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;\n plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;\n debug?: boolean;\n} & IndexerStartingCursor;\n\nexport type IndexerWithStreamConfig<TFilter, TBlock> = IndexerConfig<\n TFilter,\n TBlock\n> & {\n streamConfig: StreamConfig<TFilter, TBlock>;\n};\n\nexport function defineIndexer<TFilter, TBlock>(\n streamConfig: StreamConfig<TFilter, TBlock>,\n) {\n return (\n config: IndexerConfig<TFilter, TBlock>,\n ): IndexerWithStreamConfig<TFilter, TBlock> => ({\n streamConfig,\n ...config,\n });\n}\n\nexport interface Indexer<TFilter, TBlock> {\n streamConfig: StreamConfig<TFilter, TBlock>;\n options: IndexerConfig<TFilter, TBlock>;\n hooks: Hookable<IndexerHooks<TFilter, TBlock>>;\n}\n\nexport function createIndexer<TFilter, TBlock>({\n streamConfig,\n ...options\n}: IndexerWithStreamConfig<TFilter, TBlock>) {\n const indexer: Indexer<TFilter, TBlock> = {\n options,\n streamConfig,\n hooks: createHooks<IndexerHooks<TFilter, TBlock>>(),\n };\n\n if (indexer.options.debug) {\n createDebugger(indexer.hooks, { tag: \"indexer\" });\n }\n\n indexer.hooks.addHooks(indexer.options.hooks ?? {});\n\n for (const plugin of indexer.options.plugins ?? []) {\n plugin(indexer);\n }\n\n return indexer;\n}\n\nexport interface ReconnectOptions {\n maxRetries?: number;\n retryDelay?: number;\n maxWait?: number;\n}\n\nexport async function runWithReconnect<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n options: ReconnectOptions = {},\n) {\n let retryCount = 0;\n\n const maxRetries = options.maxRetries ?? 10;\n const retryDelay = options.retryDelay ?? 1_000;\n const maxWait = options.maxWait ?? 30_000;\n\n const runOptions: RunOptions = {\n onConnect() {\n retryCount = 0;\n },\n };\n\n while (true) {\n try {\n await run(client, indexer, runOptions);\n return;\n } catch (error) {\n // Only reconnect on internal/server errors.\n // All other errors should be rethrown.\n\n retryCount++;\n\n if (error instanceof ClientError || error instanceof ServerError) {\n const isServerError = error instanceof ServerError;\n\n if (error.code === Status.INTERNAL) {\n if (retryCount < maxRetries) {\n consola.error(\n `Internal ${isServerError ? \"server\" : \"client\"} error: ${\n error.message\n }`,\n );\n consola.start(\"Reconnecting...\");\n console.log();\n\n // Add jitter to the retry delay to avoid all clients retrying at the same time.\n const delay = Math.random() * (retryDelay * 0.2) + retryDelay;\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(retryCount * delay, maxWait)),\n );\n\n continue;\n }\n }\n }\n\n throw error;\n }\n }\n}\n\nexport interface RunOptions {\n onConnect?: () => void | Promise<void>;\n}\n\nexport async function run<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n runOptions: RunOptions = {},\n) {\n await indexerAsyncContext.callAsync({}, async () => {\n const context = useIndexerContext();\n\n if (indexer.options.debug) {\n context.debug = true;\n }\n\n await indexer.hooks.callHook(\"plugins:init\");\n\n const middleware = await registerMiddleware(indexer);\n\n const indexerMetrics = createIndexerMetrics();\n const tracer = createTracer();\n\n await indexer.hooks.callHook(\"run:before\");\n\n const { indexerName: indexerId } = useInternalContext();\n\n const isFactoryMode = indexer.options.factory !== undefined;\n\n // Give priority to startingCursor over startingBlock.\n let startingCursor: Cursor | undefined;\n if (indexer.options.startingCursor) {\n startingCursor = indexer.options.startingCursor;\n } else if (indexer.options.startingBlock !== undefined) {\n if (indexer.options.startingBlock === 0n) {\n startingCursor = undefined;\n } else if (indexer.options.startingBlock > 0n) {\n startingCursor = {\n orderKey: indexer.options.startingBlock - 1n,\n };\n }\n }\n\n // if factory mode we add a empty filter at the end of the filter array.\n const request = {\n filter: isFactoryMode\n ? [indexer.options.filter, {} as TFilter]\n : [indexer.options.filter],\n finality: indexer.options.finality,\n startingCursor,\n } as StreamDataRequest<TFilter>;\n\n const options: StreamDataOptions = {};\n\n await indexer.hooks.callHook(\"connect:before\", { request, options });\n\n // store main filter, so later it can be merged\n let mainFilter: TFilter;\n if (isFactoryMode) {\n mainFilter = request.filter[1];\n }\n\n let stream: AsyncIterator<\n StreamDataResponse<TBlock>,\n StreamDataResponse<TBlock>\n > = client.streamData(request, options)[Symbol.asyncIterator]();\n\n await indexer.hooks.callHook(\"connect:after\", { request });\n\n let onConnectCalled = false;\n\n while (true) {\n const { value: message, done } = await stream.next();\n\n if (done) {\n break;\n }\n\n if (!onConnectCalled) {\n onConnectCalled = true;\n if (runOptions.onConnect) {\n await runOptions.onConnect();\n }\n }\n\n await indexer.hooks.callHook(\"message\", { message });\n\n switch (message._tag) {\n case \"data\": {\n await tracer.startActiveSpan(\"message data\", async (span) => {\n const blocks = message.data.data;\n const { cursor, endCursor, finality, production } = message.data;\n\n context.cursor = cursor;\n context.endCursor = endCursor;\n context.finality = finality;\n\n // Record current block number being processed\n indexerMetrics.currentBlockGauge.record(\n Number(endCursor?.orderKey),\n {\n indexer_id: indexerId,\n },\n );\n\n await middleware(context, async () => {\n let block: TBlock | null;\n\n // when factory mode\n if (isFactoryMode && finality !== \"pending\") {\n assert(indexer.options.factory !== undefined);\n\n const [factoryBlock, mainBlock] = blocks;\n\n block = mainBlock;\n\n if (factoryBlock !== null) {\n const { filter } = await indexer.options.factory({\n block: factoryBlock,\n cursor,\n endCursor,\n finality,\n production,\n context,\n });\n\n // write returned data from factory function if filter is not defined\n if (filter) {\n // when filter is defined\n // merge old and new filters\n mainFilter = indexer.streamConfig.mergeFilter(\n mainFilter,\n filter,\n );\n\n // create request with new filters\n const request = {\n filter: [indexer.options.filter, mainFilter],\n finality: indexer.options.finality,\n startingCursor: cursor,\n } as StreamDataRequest<TFilter>;\n\n await indexer.hooks.callHook(\"connect:factory\", {\n request,\n endCursor,\n });\n\n // create new stream with new request\n stream = client\n .streamData(request, options)\n [Symbol.asyncIterator]();\n\n const { value: message } = await stream.next();\n\n assert(message._tag === \"data\");\n\n const [_factoryBlock, _block] = message.data.data;\n\n block = _block;\n }\n }\n } else {\n // when not in factory mode\n block = blocks[0];\n }\n\n // if block is not null\n if (block) {\n await tracer.startActiveSpan(\"handler\", async (span) => {\n await indexer.options.transform({\n block,\n cursor,\n endCursor,\n finality,\n production,\n context,\n });\n\n span.end();\n });\n }\n });\n\n span.end();\n });\n\n // Record processed block metric\n indexerMetrics.processedBlockCounter.add(1, {\n indexer_id: indexerId,\n });\n\n context.cursor = undefined;\n context.endCursor = undefined;\n context.finality = undefined;\n\n break;\n }\n case \"invalidate\": {\n await tracer.startActiveSpan(\"message invalidate\", async (span) => {\n // Record reorg metric\n indexerMetrics.reorgCounter.add(1, {\n indexer_id: indexerId,\n });\n await indexer.hooks.callHook(\"message:invalidate\", {\n message: message.invalidate,\n });\n span.end();\n });\n break;\n }\n case \"finalize\": {\n await tracer.startActiveSpan(\"message finalize\", async (span) => {\n await indexer.hooks.callHook(\"message:finalize\", {\n message: message.finalize,\n });\n span.end();\n });\n break;\n }\n case \"heartbeat\": {\n await tracer.startActiveSpan(\"message heartbeat\", async (span) => {\n await indexer.hooks.callHook(\"message:heartbeat\");\n span.end();\n });\n break;\n }\n case \"systemMessage\": {\n await tracer.startActiveSpan(\n \"message systemMessage\",\n async (span) => {\n switch (message.systemMessage.output?._tag) {\n case \"stderr\": {\n consola.warn(message.systemMessage.output.stderr);\n break;\n }\n case \"stdout\": {\n consola.info(message.systemMessage.output.stdout);\n break;\n }\n default: {\n }\n }\n\n await indexer.hooks.callHook(\"message:systemMessage\", {\n message: message.systemMessage,\n });\n span.end();\n },\n );\n break;\n }\n default: {\n consola.warn(\"unexpected message\", message);\n throw new Error(\"not implemented\");\n }\n }\n\n await indexer.hooks.callHook(\"run:after\");\n }\n });\n}\n\nasync function registerMiddleware<TFilter, TBlock>(\n indexer: Indexer<TFilter, TBlock>,\n): Promise<MiddlewareFunction<IndexerContext>> {\n const middleware: MiddlewareFunction<IndexerContext>[] = [];\n const use = (fn: MiddlewareFunction<IndexerContext>) => {\n middleware.push(fn);\n };\n\n await indexer.hooks.callHook(\"handler:middleware\", { use });\n\n const composed = compose(middleware);\n\n // Return a named function to help debugging\n return async function _composedIndexerMiddleware(\n context: IndexerContext,\n next?: NextFunction,\n ) {\n await composed(context, next);\n };\n}\n"],"names":["trace","metrics","createHooks","createDebugger","ClientError","ServerError","Status","consola","indexerAsyncContext","useIndexerContext","useInternalContext","assert","request","message","span"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/compose.ts","../src/otel.ts","../src/utils/index.ts","../src/indexer.ts"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2021 - present, Yusuke Wada and Hono contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { IndexerContext } from \"./context\";\n\nexport type NextFunction = () => Promise<void>;\nexport type MiddlewareFunction<C> = (\n context: C,\n next: NextFunction,\n) => Promise<void>;\n\nexport function compose<C extends IndexerContext>(\n middleware: MiddlewareFunction<C>[],\n): (context: C, next?: NextFunction) => Promise<void> {\n return (context, next) => {\n let index = -1;\n\n return dispatch(0);\n\n /// Dispatch the middleware functions.\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n let handler: MiddlewareFunction<C> | undefined;\n\n if (i >= middleware.length) {\n if (next) {\n await next();\n }\n\n return;\n }\n\n if (middleware[i]) {\n handler = middleware[i];\n } else {\n handler = i === middleware.length ? next : undefined;\n }\n\n if (!handler) {\n throw new Error(\"Handler not found\");\n }\n\n await handler(context, () => dispatch(i + 1));\n }\n };\n}\n","import { metrics, trace } from \"@opentelemetry/api\";\n\nexport function createTracer() {\n return trace.getTracer(\"@apibara/indexer\");\n}\n\nexport function createIndexerMetrics() {\n const meter = metrics.getMeter(\"@apibara/indexer\");\n\n const currentBlockGauge = meter.createGauge(\"current_block\", {\n description: \"Current block number being processed\",\n unit: \"{block}\",\n });\n\n const processedBlockCounter = meter.createCounter(\"processed_blocks\", {\n description: \"Number of blocks processed\",\n unit: \"{blocks}\",\n });\n\n const reorgCounter = meter.createCounter(\"reorgs\", {\n description: \"Number of reorgs (invalidate messages) received\",\n unit: \"{reorgs}\",\n });\n\n return {\n currentBlockGauge,\n processedBlockCounter,\n reorgCounter,\n };\n}\n","import { useIndexerContext } from \"../context\";\n\nexport function reloadIndexer() {\n const context = useIndexerContext();\n context._reload = true;\n}\n\nexport function reloadIfNeeded() {\n const context = useIndexerContext();\n if (context._reload) {\n context._reload = false;\n throw new ReloadIndexerRequest();\n }\n}\n\nexport class ReloadIndexerRequest extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"ReloadIndexerRequest\";\n }\n}\n","import {\n type Client,\n ClientError,\n type CreateClientOptions,\n type Cursor,\n type DataFinality,\n type DataProduction,\n type Finalize,\n type Invalidate,\n ServerError,\n Status,\n type StreamConfig,\n type StreamDataOptions,\n type StreamDataRequest,\n type StreamDataResponse,\n type SystemMessage,\n} from \"@apibara/protocol\";\nimport consola from \"consola\";\nimport {\n type Hookable,\n type NestedHooks,\n createDebugger,\n createHooks,\n} from \"hookable\";\n\nimport assert from \"node:assert\";\nimport { type MiddlewareFunction, type NextFunction, compose } from \"./compose\";\nimport {\n type IndexerContext,\n indexerAsyncContext,\n useIndexerContext,\n} from \"./context\";\nimport { createIndexerMetrics, createTracer } from \"./otel\";\nimport type { IndexerPlugin } from \"./plugins\";\nimport { useInternalContext } from \"./plugins/context\";\nimport { reloadIfNeeded } from \"./utils\";\n\nexport type UseMiddlewareFunction = (\n fn: MiddlewareFunction<IndexerContext>,\n) => void;\n\nexport interface IndexerHooks<TFilter, TBlock> {\n \"plugins:init\": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;\n \"run:before\": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;\n \"run:after\": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;\n \"connect:before\": ({\n request,\n options,\n }: {\n request: StreamDataRequest<TFilter>;\n options: StreamDataOptions;\n abortSignal?: AbortSignal;\n }) => void;\n \"connect:after\": ({\n request,\n }: {\n request: StreamDataRequest<TFilter>;\n abortSignal?: AbortSignal;\n }) => void;\n \"connect:factory\": ({\n request,\n endCursor,\n abortSignal,\n }: {\n request: StreamDataRequest<TFilter>;\n endCursor?: Cursor;\n abortSignal?: AbortSignal;\n }) => void;\n \"handler:middleware\": ({\n use,\n abortSignal,\n }: { use: UseMiddlewareFunction; abortSignal?: AbortSignal }) => void;\n message: ({\n message,\n abortSignal,\n }: {\n message: StreamDataResponse<TBlock>;\n abortSignal?: AbortSignal;\n }) => void;\n \"message:invalidate\": ({\n message,\n abortSignal,\n }: { message: Invalidate; abortSignal?: AbortSignal }) => void;\n \"message:finalize\": ({\n message,\n abortSignal,\n }: { message: Finalize; abortSignal?: AbortSignal }) => void;\n \"message:heartbeat\": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;\n \"message:systemMessage\": ({\n message,\n abortSignal,\n }: { message: SystemMessage; abortSignal?: AbortSignal }) => void;\n}\n\nexport type IndexerStartingCursor =\n | {\n startingCursor?: never;\n startingBlock: bigint;\n }\n | {\n startingCursor: Cursor;\n startingBlock?: never;\n }\n | {\n startingCursor?: never;\n startingBlock?: never;\n };\n\nexport type HandlerArgs<TBlock> = {\n block: TBlock;\n cursor?: Cursor | undefined;\n endCursor?: Cursor | undefined;\n finality: DataFinality;\n production: DataProduction;\n context: IndexerContext;\n abortSignal?: AbortSignal;\n};\n\nexport type IndexerConfig<TFilter, TBlock> = {\n streamUrl: string;\n filter: TFilter;\n finality?: DataFinality;\n clientOptions?: CreateClientOptions;\n factory?: (args: HandlerArgs<TBlock>) => Promise<{\n filter?: TFilter;\n }>;\n transform: (args: HandlerArgs<TBlock>) => Promise<void>;\n hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;\n plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;\n debug?: boolean;\n} & IndexerStartingCursor;\n\nexport type IndexerWithStreamConfig<TFilter, TBlock> = IndexerConfig<\n TFilter,\n TBlock\n> & {\n streamConfig: StreamConfig<TFilter, TBlock>;\n};\n\nexport function defineIndexer<TFilter, TBlock>(\n streamConfig: StreamConfig<TFilter, TBlock>,\n) {\n return (\n config: IndexerConfig<TFilter, TBlock>,\n ): IndexerWithStreamConfig<TFilter, TBlock> => ({\n streamConfig,\n ...config,\n });\n}\n\nexport interface Indexer<TFilter, TBlock> {\n streamConfig: StreamConfig<TFilter, TBlock>;\n options: IndexerConfig<TFilter, TBlock>;\n hooks: Hookable<IndexerHooks<TFilter, TBlock>>;\n}\n\nexport function createIndexer<TFilter, TBlock>({\n streamConfig,\n ...options\n}: IndexerWithStreamConfig<TFilter, TBlock>) {\n const indexer: Indexer<TFilter, TBlock> = {\n options,\n streamConfig,\n hooks: createHooks<IndexerHooks<TFilter, TBlock>>(),\n };\n\n if (indexer.options.debug) {\n createDebugger(indexer.hooks, { tag: \"indexer\" });\n }\n\n indexer.hooks.addHooks(indexer.options.hooks ?? {});\n\n for (const plugin of indexer.options.plugins ?? []) {\n plugin(indexer);\n }\n\n return indexer;\n}\n\nexport interface ReconnectOptions {\n maxRetries?: number;\n retryDelay?: number;\n maxWait?: number;\n}\n\nexport async function runWithReconnect<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n options: ReconnectOptions = {},\n) {\n let retryCount = 0;\n\n const maxRetries = options.maxRetries ?? 10;\n const retryDelay = options.retryDelay ?? 1_000;\n const maxWait = options.maxWait ?? 30_000;\n\n while (true) {\n const abortController = new AbortController();\n\n const runOptions: RunOptions = {\n onConnect() {\n retryCount = 0;\n },\n abortSignal: abortController.signal,\n };\n\n try {\n await run(client, indexer, runOptions);\n abortController.abort();\n return;\n } catch (error) {\n // Only reconnect on internal/server errors.\n // All other errors should be rethrown.\n\n retryCount++;\n\n abortController.abort();\n\n if (error instanceof ClientError || error instanceof ServerError) {\n const isServerError = error instanceof ServerError;\n\n if (error.code === Status.INTERNAL) {\n if (retryCount < maxRetries) {\n consola.error(\n `Internal ${isServerError ? \"server\" : \"client\"} error: ${\n error.message\n }`,\n );\n consola.start(\"Reconnecting...\");\n console.log();\n\n // Add jitter to the retry delay to avoid all clients retrying at the same time.\n const delay = Math.random() * (retryDelay * 0.2) + retryDelay;\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(retryCount * delay, maxWait)),\n );\n\n continue;\n }\n }\n }\n throw error;\n }\n }\n}\n\nexport interface RunOptions {\n onConnect?: () => void | Promise<void>;\n abortSignal?: AbortSignal;\n}\n\nexport async function run<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n runOptions: RunOptions = {},\n) {\n await indexerAsyncContext.callAsync({}, async () => {\n const context = useIndexerContext();\n\n if (indexer.options.debug) {\n context.debug = true;\n }\n\n const { abortSignal } = runOptions;\n\n await indexer.hooks.callHook(\"plugins:init\", { abortSignal });\n\n const middleware = await registerMiddleware(indexer, abortSignal);\n\n const indexerMetrics = createIndexerMetrics();\n const tracer = createTracer();\n\n await indexer.hooks.callHook(\"run:before\", { abortSignal });\n\n const { indexerName: indexerId } = useInternalContext();\n\n const isFactoryMode = indexer.options.factory !== undefined;\n\n // Give priority to startingCursor over startingBlock.\n let startingCursor: Cursor | undefined;\n if (indexer.options.startingCursor) {\n startingCursor = indexer.options.startingCursor;\n } else if (indexer.options.startingBlock !== undefined) {\n if (indexer.options.startingBlock === 0n) {\n startingCursor = undefined;\n } else if (indexer.options.startingBlock > 0n) {\n startingCursor = {\n orderKey: indexer.options.startingBlock - 1n,\n };\n }\n }\n\n // if factory mode we add a empty filter at the end of the filter array.\n const request = {\n filter: isFactoryMode\n ? [indexer.options.filter, {} as TFilter]\n : [indexer.options.filter],\n finality: indexer.options.finality,\n startingCursor,\n } as StreamDataRequest<TFilter>;\n\n const options: StreamDataOptions = {};\n\n await indexer.hooks.callHook(\"connect:before\", {\n request,\n options,\n abortSignal,\n });\n\n // store main filter, so later it can be merged\n let mainFilter: TFilter;\n if (isFactoryMode) {\n mainFilter = request.filter[1];\n }\n\n let stream: AsyncIterator<\n StreamDataResponse<TBlock>,\n StreamDataResponse<TBlock>\n > = client.streamData(request, options)[Symbol.asyncIterator]();\n\n await indexer.hooks.callHook(\"connect:after\", { request, abortSignal });\n\n let onConnectCalled = false;\n\n while (true) {\n const { value: message, done } = await stream.next();\n\n if (done) {\n break;\n }\n\n if (!onConnectCalled) {\n onConnectCalled = true;\n if (runOptions.onConnect) {\n await runOptions.onConnect();\n }\n }\n\n await indexer.hooks.callHook(\"message\", { message, abortSignal });\n\n switch (message._tag) {\n case \"data\": {\n await tracer.startActiveSpan(\"message data\", async (span) => {\n const blocks = message.data.data;\n const { cursor, endCursor, finality, production } = message.data;\n\n context.cursor = cursor;\n context.endCursor = endCursor;\n context.finality = finality;\n\n // Record current block number being processed\n indexerMetrics.currentBlockGauge.record(\n Number(endCursor?.orderKey),\n {\n indexer_id: indexerId,\n },\n );\n\n reloadIfNeeded();\n\n await middleware(context, async () => {\n let block: TBlock | null;\n\n // when factory mode\n if (isFactoryMode && finality !== \"pending\") {\n assert(indexer.options.factory !== undefined);\n\n const [factoryBlock, mainBlock] = blocks;\n\n block = mainBlock;\n\n if (factoryBlock !== null) {\n const { filter } = await indexer.options.factory({\n block: factoryBlock,\n cursor,\n endCursor,\n finality,\n production,\n context,\n abortSignal,\n });\n\n // write returned data from factory function if filter is not defined\n if (filter) {\n // when filter is defined\n // merge old and new filters\n mainFilter = indexer.streamConfig.mergeFilter(\n mainFilter,\n filter,\n );\n\n // create request with new filters\n const request = {\n filter: [indexer.options.filter, mainFilter],\n finality: indexer.options.finality,\n startingCursor: cursor,\n } as StreamDataRequest<TFilter>;\n\n await indexer.hooks.callHook(\"connect:factory\", {\n request,\n endCursor,\n abortSignal,\n });\n\n // create new stream with new request\n stream = client\n .streamData(request, options)\n [Symbol.asyncIterator]();\n\n const { value: message } = await stream.next();\n\n assert(message._tag === \"data\");\n\n const [_factoryBlock, _block] = message.data.data;\n\n block = _block;\n }\n }\n } else {\n // when not in factory mode\n block = blocks[0];\n }\n\n // if block is not null\n if (block) {\n await tracer.startActiveSpan(\"handler\", async (span) => {\n await indexer.options.transform({\n block,\n cursor,\n endCursor,\n finality,\n production,\n context,\n abortSignal,\n });\n\n span.end();\n });\n }\n });\n\n reloadIfNeeded();\n\n span.end();\n });\n\n // Record processed block metric\n indexerMetrics.processedBlockCounter.add(1, {\n indexer_id: indexerId,\n });\n\n context.cursor = undefined;\n context.endCursor = undefined;\n context.finality = undefined;\n\n break;\n }\n case \"invalidate\": {\n await tracer.startActiveSpan(\"message invalidate\", async (span) => {\n // Record reorg metric\n indexerMetrics.reorgCounter.add(1, {\n indexer_id: indexerId,\n });\n await indexer.hooks.callHook(\"message:invalidate\", {\n message: message.invalidate,\n abortSignal,\n });\n span.end();\n });\n break;\n }\n case \"finalize\": {\n await tracer.startActiveSpan(\"message finalize\", async (span) => {\n await indexer.hooks.callHook(\"message:finalize\", {\n message: message.finalize,\n abortSignal,\n });\n span.end();\n });\n break;\n }\n case \"heartbeat\": {\n await tracer.startActiveSpan(\"message heartbeat\", async (span) => {\n reloadIfNeeded();\n\n await indexer.hooks.callHook(\"message:heartbeat\", { abortSignal });\n reloadIfNeeded();\n\n span.end();\n });\n break;\n }\n case \"systemMessage\": {\n await tracer.startActiveSpan(\n \"message systemMessage\",\n async (span) => {\n switch (message.systemMessage.output?._tag) {\n case \"stderr\": {\n consola.warn(message.systemMessage.output.stderr);\n break;\n }\n case \"stdout\": {\n consola.info(message.systemMessage.output.stdout);\n break;\n }\n default: {\n }\n }\n\n await indexer.hooks.callHook(\"message:systemMessage\", {\n message: message.systemMessage,\n abortSignal,\n });\n span.end();\n },\n );\n break;\n }\n default: {\n consola.warn(\"unexpected message\", message);\n throw new Error(\"not implemented\");\n }\n }\n }\n\n await indexer.hooks.callHook(\"run:after\", { abortSignal });\n });\n}\n\nasync function registerMiddleware<TFilter, TBlock>(\n indexer: Indexer<TFilter, TBlock>,\n abortSignal?: AbortSignal,\n): Promise<MiddlewareFunction<IndexerContext>> {\n const middleware: MiddlewareFunction<IndexerContext>[] = [];\n const use = (fn: MiddlewareFunction<IndexerContext>) => {\n middleware.push(fn);\n };\n\n await indexer.hooks.callHook(\"handler:middleware\", { use, abortSignal });\n\n const composed = compose(middleware);\n\n // Return a named function to help debugging\n return async function _composedIndexerMiddleware(\n context: IndexerContext,\n next?: NextFunction,\n ) {\n await composed(context, next);\n };\n}\n"],"names":["trace","metrics","useIndexerContext","createHooks","createDebugger","ClientError","ServerError","Status","consola","indexerAsyncContext","useInternalContext","assert","request","message","span"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export { H as HandlerArgs,
|
|
1
|
+
export { H as HandlerArgs, e as Indexer, b as IndexerConfig, I as IndexerHooks, a as IndexerStartingCursor, c as IndexerWithStreamConfig, R as ReconnectOptions, g as RunOptions, U as UseMiddlewareFunction, f as createIndexer, d as defineIndexer, h as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.4ef52548.cjs';
|
|
2
2
|
import '@apibara/protocol';
|
|
3
3
|
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare function reloadIndexer(): void;
|
|
6
|
+
declare class ReloadIndexerRequest extends Error {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { ReloadIndexerRequest, reloadIndexer };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export { H as HandlerArgs,
|
|
1
|
+
export { H as HandlerArgs, e as Indexer, b as IndexerConfig, I as IndexerHooks, a as IndexerStartingCursor, c as IndexerWithStreamConfig, R as ReconnectOptions, g as RunOptions, U as UseMiddlewareFunction, f as createIndexer, d as defineIndexer, h as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.4ef52548.mjs';
|
|
2
2
|
import '@apibara/protocol';
|
|
3
3
|
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare function reloadIndexer(): void;
|
|
6
|
+
declare class ReloadIndexerRequest extends Error {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { ReloadIndexerRequest, reloadIndexer };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export { H as HandlerArgs,
|
|
1
|
+
export { H as HandlerArgs, e as Indexer, b as IndexerConfig, I as IndexerHooks, a as IndexerStartingCursor, c as IndexerWithStreamConfig, R as ReconnectOptions, g as RunOptions, U as UseMiddlewareFunction, f as createIndexer, d as defineIndexer, h as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.4ef52548.js';
|
|
2
2
|
import '@apibara/protocol';
|
|
3
3
|
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare function reloadIndexer(): void;
|
|
6
|
+
declare class ReloadIndexerRequest extends Error {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { ReloadIndexerRequest, reloadIndexer };
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { ClientError, ServerError, Status } from '@apibara/protocol';
|
|
|
2
2
|
import consola from 'consola';
|
|
3
3
|
import { createHooks, createDebugger } from 'hookable';
|
|
4
4
|
import assert from 'node:assert';
|
|
5
|
-
import {
|
|
5
|
+
import { u as useIndexerContext, i as indexerAsyncContext } from './shared/indexer.75773ef1.mjs';
|
|
6
6
|
import { trace, metrics } from '@opentelemetry/api';
|
|
7
7
|
import { useInternalContext } from './internal/plugins.mjs';
|
|
8
8
|
import 'node:async_hooks';
|
|
@@ -61,6 +61,24 @@ function createIndexerMetrics() {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
function reloadIndexer() {
|
|
65
|
+
const context = useIndexerContext();
|
|
66
|
+
context._reload = true;
|
|
67
|
+
}
|
|
68
|
+
function reloadIfNeeded() {
|
|
69
|
+
const context = useIndexerContext();
|
|
70
|
+
if (context._reload) {
|
|
71
|
+
context._reload = false;
|
|
72
|
+
throw new ReloadIndexerRequest();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
class ReloadIndexerRequest extends Error {
|
|
76
|
+
constructor(message) {
|
|
77
|
+
super(message);
|
|
78
|
+
this.name = "ReloadIndexerRequest";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
function defineIndexer(streamConfig) {
|
|
65
83
|
return (config) => ({
|
|
66
84
|
streamConfig,
|
|
@@ -90,17 +108,21 @@ async function runWithReconnect(client, indexer, options = {}) {
|
|
|
90
108
|
const maxRetries = options.maxRetries ?? 10;
|
|
91
109
|
const retryDelay = options.retryDelay ?? 1e3;
|
|
92
110
|
const maxWait = options.maxWait ?? 3e4;
|
|
93
|
-
const runOptions = {
|
|
94
|
-
onConnect() {
|
|
95
|
-
retryCount = 0;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
111
|
while (true) {
|
|
112
|
+
const abortController = new AbortController();
|
|
113
|
+
const runOptions = {
|
|
114
|
+
onConnect() {
|
|
115
|
+
retryCount = 0;
|
|
116
|
+
},
|
|
117
|
+
abortSignal: abortController.signal
|
|
118
|
+
};
|
|
99
119
|
try {
|
|
100
120
|
await run(client, indexer, runOptions);
|
|
121
|
+
abortController.abort();
|
|
101
122
|
return;
|
|
102
123
|
} catch (error) {
|
|
103
124
|
retryCount++;
|
|
125
|
+
abortController.abort();
|
|
104
126
|
if (error instanceof ClientError || error instanceof ServerError) {
|
|
105
127
|
const isServerError = error instanceof ServerError;
|
|
106
128
|
if (error.code === Status.INTERNAL) {
|
|
@@ -128,11 +150,12 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
128
150
|
if (indexer.options.debug) {
|
|
129
151
|
context.debug = true;
|
|
130
152
|
}
|
|
131
|
-
|
|
132
|
-
|
|
153
|
+
const { abortSignal } = runOptions;
|
|
154
|
+
await indexer.hooks.callHook("plugins:init", { abortSignal });
|
|
155
|
+
const middleware = await registerMiddleware(indexer, abortSignal);
|
|
133
156
|
const indexerMetrics = createIndexerMetrics();
|
|
134
157
|
const tracer = createTracer();
|
|
135
|
-
await indexer.hooks.callHook("run:before");
|
|
158
|
+
await indexer.hooks.callHook("run:before", { abortSignal });
|
|
136
159
|
const { indexerName: indexerId } = useInternalContext();
|
|
137
160
|
const isFactoryMode = indexer.options.factory !== void 0;
|
|
138
161
|
let startingCursor;
|
|
@@ -153,13 +176,17 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
153
176
|
startingCursor
|
|
154
177
|
};
|
|
155
178
|
const options = {};
|
|
156
|
-
await indexer.hooks.callHook("connect:before", {
|
|
179
|
+
await indexer.hooks.callHook("connect:before", {
|
|
180
|
+
request,
|
|
181
|
+
options,
|
|
182
|
+
abortSignal
|
|
183
|
+
});
|
|
157
184
|
let mainFilter;
|
|
158
185
|
if (isFactoryMode) {
|
|
159
186
|
mainFilter = request.filter[1];
|
|
160
187
|
}
|
|
161
188
|
let stream = client.streamData(request, options)[Symbol.asyncIterator]();
|
|
162
|
-
await indexer.hooks.callHook("connect:after", { request });
|
|
189
|
+
await indexer.hooks.callHook("connect:after", { request, abortSignal });
|
|
163
190
|
let onConnectCalled = false;
|
|
164
191
|
while (true) {
|
|
165
192
|
const { value: message, done } = await stream.next();
|
|
@@ -172,7 +199,7 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
172
199
|
await runOptions.onConnect();
|
|
173
200
|
}
|
|
174
201
|
}
|
|
175
|
-
await indexer.hooks.callHook("message", { message });
|
|
202
|
+
await indexer.hooks.callHook("message", { message, abortSignal });
|
|
176
203
|
switch (message._tag) {
|
|
177
204
|
case "data": {
|
|
178
205
|
await tracer.startActiveSpan("message data", async (span) => {
|
|
@@ -187,6 +214,7 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
187
214
|
indexer_id: indexerId
|
|
188
215
|
}
|
|
189
216
|
);
|
|
217
|
+
reloadIfNeeded();
|
|
190
218
|
await middleware(context, async () => {
|
|
191
219
|
let block;
|
|
192
220
|
if (isFactoryMode && finality !== "pending") {
|
|
@@ -200,7 +228,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
200
228
|
endCursor,
|
|
201
229
|
finality,
|
|
202
230
|
production,
|
|
203
|
-
context
|
|
231
|
+
context,
|
|
232
|
+
abortSignal
|
|
204
233
|
});
|
|
205
234
|
if (filter) {
|
|
206
235
|
mainFilter = indexer.streamConfig.mergeFilter(
|
|
@@ -214,7 +243,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
214
243
|
};
|
|
215
244
|
await indexer.hooks.callHook("connect:factory", {
|
|
216
245
|
request: request2,
|
|
217
|
-
endCursor
|
|
246
|
+
endCursor,
|
|
247
|
+
abortSignal
|
|
218
248
|
});
|
|
219
249
|
stream = client.streamData(request2, options)[Symbol.asyncIterator]();
|
|
220
250
|
const { value: message2 } = await stream.next();
|
|
@@ -234,12 +264,14 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
234
264
|
endCursor,
|
|
235
265
|
finality,
|
|
236
266
|
production,
|
|
237
|
-
context
|
|
267
|
+
context,
|
|
268
|
+
abortSignal
|
|
238
269
|
});
|
|
239
270
|
span2.end();
|
|
240
271
|
});
|
|
241
272
|
}
|
|
242
273
|
});
|
|
274
|
+
reloadIfNeeded();
|
|
243
275
|
span.end();
|
|
244
276
|
});
|
|
245
277
|
indexerMetrics.processedBlockCounter.add(1, {
|
|
@@ -256,7 +288,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
256
288
|
indexer_id: indexerId
|
|
257
289
|
});
|
|
258
290
|
await indexer.hooks.callHook("message:invalidate", {
|
|
259
|
-
message: message.invalidate
|
|
291
|
+
message: message.invalidate,
|
|
292
|
+
abortSignal
|
|
260
293
|
});
|
|
261
294
|
span.end();
|
|
262
295
|
});
|
|
@@ -265,7 +298,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
265
298
|
case "finalize": {
|
|
266
299
|
await tracer.startActiveSpan("message finalize", async (span) => {
|
|
267
300
|
await indexer.hooks.callHook("message:finalize", {
|
|
268
|
-
message: message.finalize
|
|
301
|
+
message: message.finalize,
|
|
302
|
+
abortSignal
|
|
269
303
|
});
|
|
270
304
|
span.end();
|
|
271
305
|
});
|
|
@@ -273,7 +307,9 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
273
307
|
}
|
|
274
308
|
case "heartbeat": {
|
|
275
309
|
await tracer.startActiveSpan("message heartbeat", async (span) => {
|
|
276
|
-
|
|
310
|
+
reloadIfNeeded();
|
|
311
|
+
await indexer.hooks.callHook("message:heartbeat", { abortSignal });
|
|
312
|
+
reloadIfNeeded();
|
|
277
313
|
span.end();
|
|
278
314
|
});
|
|
279
315
|
break;
|
|
@@ -293,7 +329,8 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
293
329
|
}
|
|
294
330
|
}
|
|
295
331
|
await indexer.hooks.callHook("message:systemMessage", {
|
|
296
|
-
message: message.systemMessage
|
|
332
|
+
message: message.systemMessage,
|
|
333
|
+
abortSignal
|
|
297
334
|
});
|
|
298
335
|
span.end();
|
|
299
336
|
}
|
|
@@ -305,21 +342,21 @@ async function run(client, indexer, runOptions = {}) {
|
|
|
305
342
|
throw new Error("not implemented");
|
|
306
343
|
}
|
|
307
344
|
}
|
|
308
|
-
await indexer.hooks.callHook("run:after");
|
|
309
345
|
}
|
|
346
|
+
await indexer.hooks.callHook("run:after", { abortSignal });
|
|
310
347
|
});
|
|
311
348
|
}
|
|
312
|
-
async function registerMiddleware(indexer) {
|
|
349
|
+
async function registerMiddleware(indexer, abortSignal) {
|
|
313
350
|
const middleware = [];
|
|
314
351
|
const use = (fn) => {
|
|
315
352
|
middleware.push(fn);
|
|
316
353
|
};
|
|
317
|
-
await indexer.hooks.callHook("handler:middleware", { use });
|
|
354
|
+
await indexer.hooks.callHook("handler:middleware", { use, abortSignal });
|
|
318
355
|
const composed = compose(middleware);
|
|
319
356
|
return async function _composedIndexerMiddleware(context, next) {
|
|
320
357
|
await composed(context, next);
|
|
321
358
|
};
|
|
322
359
|
}
|
|
323
360
|
|
|
324
|
-
export { createIndexer, defineIndexer, run, runWithReconnect, useIndexerContext };
|
|
361
|
+
export { ReloadIndexerRequest, createIndexer, defineIndexer, reloadIndexer, run, runWithReconnect, useIndexerContext };
|
|
325
362
|
//# sourceMappingURL=index.mjs.map
|