@apibara/indexer 2.1.0-beta.40 → 2.1.0-beta.41
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
|
@@ -13,35 +13,51 @@ declare function defineIndexerPlugin<TFilter, TBlock>(def: IndexerPlugin<TFilter
|
|
|
13
13
|
|
|
14
14
|
type UseMiddlewareFunction = (fn: MiddlewareFunction<IndexerContext>) => void;
|
|
15
15
|
interface IndexerHooks<TFilter, TBlock> {
|
|
16
|
-
"plugins:init": (
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
"plugins:init": ({ abortSignal }: {
|
|
17
|
+
abortSignal?: AbortSignal;
|
|
18
|
+
}) => void;
|
|
19
|
+
"run:before": ({ abortSignal }: {
|
|
20
|
+
abortSignal?: AbortSignal;
|
|
21
|
+
}) => void;
|
|
22
|
+
"run:after": ({ abortSignal }: {
|
|
23
|
+
abortSignal?: AbortSignal;
|
|
24
|
+
}) => void;
|
|
19
25
|
"connect:before": ({ request, options, }: {
|
|
20
26
|
request: StreamDataRequest<TFilter>;
|
|
21
27
|
options: StreamDataOptions;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
22
29
|
}) => void;
|
|
23
30
|
"connect:after": ({ request, }: {
|
|
24
31
|
request: StreamDataRequest<TFilter>;
|
|
32
|
+
abortSignal?: AbortSignal;
|
|
25
33
|
}) => void;
|
|
26
|
-
"connect:factory": ({ request, endCursor, }: {
|
|
34
|
+
"connect:factory": ({ request, endCursor, abortSignal, }: {
|
|
27
35
|
request: StreamDataRequest<TFilter>;
|
|
28
36
|
endCursor?: Cursor;
|
|
37
|
+
abortSignal?: AbortSignal;
|
|
29
38
|
}) => void;
|
|
30
|
-
"handler:middleware": ({ use }: {
|
|
39
|
+
"handler:middleware": ({ use, abortSignal, }: {
|
|
31
40
|
use: UseMiddlewareFunction;
|
|
41
|
+
abortSignal?: AbortSignal;
|
|
32
42
|
}) => void;
|
|
33
|
-
message: ({ message }: {
|
|
43
|
+
message: ({ message, abortSignal, }: {
|
|
34
44
|
message: StreamDataResponse<TBlock>;
|
|
45
|
+
abortSignal?: AbortSignal;
|
|
35
46
|
}) => void;
|
|
36
|
-
"message:invalidate": ({ message }: {
|
|
47
|
+
"message:invalidate": ({ message, abortSignal, }: {
|
|
37
48
|
message: Invalidate;
|
|
49
|
+
abortSignal?: AbortSignal;
|
|
38
50
|
}) => void;
|
|
39
|
-
"message:finalize": ({ message }: {
|
|
51
|
+
"message:finalize": ({ message, abortSignal, }: {
|
|
40
52
|
message: Finalize;
|
|
53
|
+
abortSignal?: AbortSignal;
|
|
54
|
+
}) => void;
|
|
55
|
+
"message:heartbeat": ({ abortSignal }: {
|
|
56
|
+
abortSignal?: AbortSignal;
|
|
41
57
|
}) => void;
|
|
42
|
-
"message:
|
|
43
|
-
"message:systemMessage": ({ message }: {
|
|
58
|
+
"message:systemMessage": ({ message, abortSignal, }: {
|
|
44
59
|
message: SystemMessage;
|
|
60
|
+
abortSignal?: AbortSignal;
|
|
45
61
|
}) => void;
|
|
46
62
|
}
|
|
47
63
|
type IndexerStartingCursor = {
|
|
@@ -61,6 +77,7 @@ type HandlerArgs<TBlock> = {
|
|
|
61
77
|
finality: DataFinality;
|
|
62
78
|
production: DataProduction;
|
|
63
79
|
context: IndexerContext;
|
|
80
|
+
abortSignal?: AbortSignal;
|
|
64
81
|
};
|
|
65
82
|
type IndexerConfig<TFilter, TBlock> = {
|
|
66
83
|
streamUrl: string;
|
|
@@ -93,7 +110,8 @@ interface ReconnectOptions {
|
|
|
93
110
|
declare function runWithReconnect<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, options?: ReconnectOptions): Promise<void>;
|
|
94
111
|
interface RunOptions {
|
|
95
112
|
onConnect?: () => void | Promise<void>;
|
|
113
|
+
abortSignal?: AbortSignal;
|
|
96
114
|
}
|
|
97
115
|
declare function run<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, runOptions?: RunOptions): Promise<void>;
|
|
98
116
|
|
|
99
|
-
export { type HandlerArgs as H, type
|
|
117
|
+
export { type HandlerArgs as H, type IndexerHooks as I, type ReconnectOptions as R, type UseMiddlewareFunction as U, type IndexerStartingCursor as a, type IndexerConfig as b, type IndexerWithStreamConfig as c, defineIndexer as d, type Indexer as e, createIndexer as f, type RunOptions as g, run as h, type IndexerPlugin as i, defineIndexerPlugin as j, runWithReconnect as r, useIndexerContext as u };
|
|
@@ -13,35 +13,51 @@ declare function defineIndexerPlugin<TFilter, TBlock>(def: IndexerPlugin<TFilter
|
|
|
13
13
|
|
|
14
14
|
type UseMiddlewareFunction = (fn: MiddlewareFunction<IndexerContext>) => void;
|
|
15
15
|
interface IndexerHooks<TFilter, TBlock> {
|
|
16
|
-
"plugins:init": (
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
"plugins:init": ({ abortSignal }: {
|
|
17
|
+
abortSignal?: AbortSignal;
|
|
18
|
+
}) => void;
|
|
19
|
+
"run:before": ({ abortSignal }: {
|
|
20
|
+
abortSignal?: AbortSignal;
|
|
21
|
+
}) => void;
|
|
22
|
+
"run:after": ({ abortSignal }: {
|
|
23
|
+
abortSignal?: AbortSignal;
|
|
24
|
+
}) => void;
|
|
19
25
|
"connect:before": ({ request, options, }: {
|
|
20
26
|
request: StreamDataRequest<TFilter>;
|
|
21
27
|
options: StreamDataOptions;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
22
29
|
}) => void;
|
|
23
30
|
"connect:after": ({ request, }: {
|
|
24
31
|
request: StreamDataRequest<TFilter>;
|
|
32
|
+
abortSignal?: AbortSignal;
|
|
25
33
|
}) => void;
|
|
26
|
-
"connect:factory": ({ request, endCursor, }: {
|
|
34
|
+
"connect:factory": ({ request, endCursor, abortSignal, }: {
|
|
27
35
|
request: StreamDataRequest<TFilter>;
|
|
28
36
|
endCursor?: Cursor;
|
|
37
|
+
abortSignal?: AbortSignal;
|
|
29
38
|
}) => void;
|
|
30
|
-
"handler:middleware": ({ use }: {
|
|
39
|
+
"handler:middleware": ({ use, abortSignal, }: {
|
|
31
40
|
use: UseMiddlewareFunction;
|
|
41
|
+
abortSignal?: AbortSignal;
|
|
32
42
|
}) => void;
|
|
33
|
-
message: ({ message }: {
|
|
43
|
+
message: ({ message, abortSignal, }: {
|
|
34
44
|
message: StreamDataResponse<TBlock>;
|
|
45
|
+
abortSignal?: AbortSignal;
|
|
35
46
|
}) => void;
|
|
36
|
-
"message:invalidate": ({ message }: {
|
|
47
|
+
"message:invalidate": ({ message, abortSignal, }: {
|
|
37
48
|
message: Invalidate;
|
|
49
|
+
abortSignal?: AbortSignal;
|
|
38
50
|
}) => void;
|
|
39
|
-
"message:finalize": ({ message }: {
|
|
51
|
+
"message:finalize": ({ message, abortSignal, }: {
|
|
40
52
|
message: Finalize;
|
|
53
|
+
abortSignal?: AbortSignal;
|
|
54
|
+
}) => void;
|
|
55
|
+
"message:heartbeat": ({ abortSignal }: {
|
|
56
|
+
abortSignal?: AbortSignal;
|
|
41
57
|
}) => void;
|
|
42
|
-
"message:
|
|
43
|
-
"message:systemMessage": ({ message }: {
|
|
58
|
+
"message:systemMessage": ({ message, abortSignal, }: {
|
|
44
59
|
message: SystemMessage;
|
|
60
|
+
abortSignal?: AbortSignal;
|
|
45
61
|
}) => void;
|
|
46
62
|
}
|
|
47
63
|
type IndexerStartingCursor = {
|
|
@@ -61,6 +77,7 @@ type HandlerArgs<TBlock> = {
|
|
|
61
77
|
finality: DataFinality;
|
|
62
78
|
production: DataProduction;
|
|
63
79
|
context: IndexerContext;
|
|
80
|
+
abortSignal?: AbortSignal;
|
|
64
81
|
};
|
|
65
82
|
type IndexerConfig<TFilter, TBlock> = {
|
|
66
83
|
streamUrl: string;
|
|
@@ -93,7 +110,8 @@ interface ReconnectOptions {
|
|
|
93
110
|
declare function runWithReconnect<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, options?: ReconnectOptions): Promise<void>;
|
|
94
111
|
interface RunOptions {
|
|
95
112
|
onConnect?: () => void | Promise<void>;
|
|
113
|
+
abortSignal?: AbortSignal;
|
|
96
114
|
}
|
|
97
115
|
declare function run<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, runOptions?: RunOptions): Promise<void>;
|
|
98
116
|
|
|
99
|
-
export { type HandlerArgs as H, type
|
|
117
|
+
export { type HandlerArgs as H, type IndexerHooks as I, type ReconnectOptions as R, type UseMiddlewareFunction as U, type IndexerStartingCursor as a, type IndexerConfig as b, type IndexerWithStreamConfig as c, defineIndexer as d, type Indexer as e, createIndexer as f, type RunOptions as g, run as h, type IndexerPlugin as i, defineIndexerPlugin as j, runWithReconnect as r, useIndexerContext as u };
|
package/dist/testing/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NestedHooks } from 'hookable';
|
|
2
|
-
import {
|
|
2
|
+
import { c as IndexerWithStreamConfig, I as IndexerHooks } from '../shared/indexer.4ef52548.cjs';
|
|
3
3
|
import '@apibara/protocol';
|
|
4
4
|
|
|
5
5
|
type VcrResult = Record<string, unknown>;
|
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NestedHooks } from 'hookable';
|
|
2
|
-
import {
|
|
2
|
+
import { c as IndexerWithStreamConfig, I as IndexerHooks } from '../shared/indexer.4ef52548.mjs';
|
|
3
3
|
import '@apibara/protocol';
|
|
4
4
|
|
|
5
5
|
type VcrResult = Record<string, unknown>;
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NestedHooks } from 'hookable';
|
|
2
|
-
import {
|
|
2
|
+
import { c as IndexerWithStreamConfig, I as IndexerHooks } from '../shared/indexer.4ef52548.js';
|
|
3
3
|
import '@apibara/protocol';
|
|
4
4
|
|
|
5
5
|
type VcrResult = Record<string, unknown>;
|
package/dist/vcr/index.d.cts
CHANGED
package/dist/vcr/index.d.mts
CHANGED
package/dist/vcr/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apibara/indexer",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.41",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"vitest": "^1.6.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@apibara/protocol": "2.1.0-beta.
|
|
73
|
+
"@apibara/protocol": "2.1.0-beta.41",
|
|
74
74
|
"@opentelemetry/api": "^1.9.0",
|
|
75
75
|
"ci-info": "^4.1.0",
|
|
76
76
|
"consola": "^3.4.2",
|
package/src/index.ts
CHANGED
package/src/indexer.ts
CHANGED
|
@@ -33,40 +33,63 @@ import {
|
|
|
33
33
|
import { createIndexerMetrics, createTracer } from "./otel";
|
|
34
34
|
import type { IndexerPlugin } from "./plugins";
|
|
35
35
|
import { useInternalContext } from "./plugins/context";
|
|
36
|
+
import { reloadIfNeeded } from "./utils";
|
|
36
37
|
|
|
37
38
|
export type UseMiddlewareFunction = (
|
|
38
39
|
fn: MiddlewareFunction<IndexerContext>,
|
|
39
40
|
) => void;
|
|
40
41
|
|
|
41
42
|
export interface IndexerHooks<TFilter, TBlock> {
|
|
42
|
-
"plugins:init": () => void;
|
|
43
|
-
"run:before": () => void;
|
|
44
|
-
"run:after": () => void;
|
|
43
|
+
"plugins:init": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;
|
|
44
|
+
"run:before": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;
|
|
45
|
+
"run:after": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;
|
|
45
46
|
"connect:before": ({
|
|
46
47
|
request,
|
|
47
48
|
options,
|
|
48
49
|
}: {
|
|
49
50
|
request: StreamDataRequest<TFilter>;
|
|
50
51
|
options: StreamDataOptions;
|
|
52
|
+
abortSignal?: AbortSignal;
|
|
51
53
|
}) => void;
|
|
52
54
|
"connect:after": ({
|
|
53
55
|
request,
|
|
54
56
|
}: {
|
|
55
57
|
request: StreamDataRequest<TFilter>;
|
|
58
|
+
abortSignal?: AbortSignal;
|
|
56
59
|
}) => void;
|
|
57
60
|
"connect:factory": ({
|
|
58
61
|
request,
|
|
59
62
|
endCursor,
|
|
63
|
+
abortSignal,
|
|
60
64
|
}: {
|
|
61
65
|
request: StreamDataRequest<TFilter>;
|
|
62
66
|
endCursor?: Cursor;
|
|
67
|
+
abortSignal?: AbortSignal;
|
|
63
68
|
}) => void;
|
|
64
|
-
"handler:middleware": ({
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
"handler:middleware": ({
|
|
70
|
+
use,
|
|
71
|
+
abortSignal,
|
|
72
|
+
}: { use: UseMiddlewareFunction; abortSignal?: AbortSignal }) => void;
|
|
73
|
+
message: ({
|
|
74
|
+
message,
|
|
75
|
+
abortSignal,
|
|
76
|
+
}: {
|
|
77
|
+
message: StreamDataResponse<TBlock>;
|
|
78
|
+
abortSignal?: AbortSignal;
|
|
79
|
+
}) => void;
|
|
80
|
+
"message:invalidate": ({
|
|
81
|
+
message,
|
|
82
|
+
abortSignal,
|
|
83
|
+
}: { message: Invalidate; abortSignal?: AbortSignal }) => void;
|
|
84
|
+
"message:finalize": ({
|
|
85
|
+
message,
|
|
86
|
+
abortSignal,
|
|
87
|
+
}: { message: Finalize; abortSignal?: AbortSignal }) => void;
|
|
88
|
+
"message:heartbeat": ({ abortSignal }: { abortSignal?: AbortSignal }) => void;
|
|
89
|
+
"message:systemMessage": ({
|
|
90
|
+
message,
|
|
91
|
+
abortSignal,
|
|
92
|
+
}: { message: SystemMessage; abortSignal?: AbortSignal }) => void;
|
|
70
93
|
}
|
|
71
94
|
|
|
72
95
|
export type IndexerStartingCursor =
|
|
@@ -90,6 +113,7 @@ export type HandlerArgs<TBlock> = {
|
|
|
90
113
|
finality: DataFinality;
|
|
91
114
|
production: DataProduction;
|
|
92
115
|
context: IndexerContext;
|
|
116
|
+
abortSignal?: AbortSignal;
|
|
93
117
|
};
|
|
94
118
|
|
|
95
119
|
export type IndexerConfig<TFilter, TBlock> = {
|
|
@@ -170,15 +194,19 @@ export async function runWithReconnect<TFilter, TBlock>(
|
|
|
170
194
|
const retryDelay = options.retryDelay ?? 1_000;
|
|
171
195
|
const maxWait = options.maxWait ?? 30_000;
|
|
172
196
|
|
|
173
|
-
const runOptions: RunOptions = {
|
|
174
|
-
onConnect() {
|
|
175
|
-
retryCount = 0;
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
|
|
179
197
|
while (true) {
|
|
198
|
+
const abortController = new AbortController();
|
|
199
|
+
|
|
200
|
+
const runOptions: RunOptions = {
|
|
201
|
+
onConnect() {
|
|
202
|
+
retryCount = 0;
|
|
203
|
+
},
|
|
204
|
+
abortSignal: abortController.signal,
|
|
205
|
+
};
|
|
206
|
+
|
|
180
207
|
try {
|
|
181
208
|
await run(client, indexer, runOptions);
|
|
209
|
+
abortController.abort();
|
|
182
210
|
return;
|
|
183
211
|
} catch (error) {
|
|
184
212
|
// Only reconnect on internal/server errors.
|
|
@@ -186,6 +214,8 @@ export async function runWithReconnect<TFilter, TBlock>(
|
|
|
186
214
|
|
|
187
215
|
retryCount++;
|
|
188
216
|
|
|
217
|
+
abortController.abort();
|
|
218
|
+
|
|
189
219
|
if (error instanceof ClientError || error instanceof ServerError) {
|
|
190
220
|
const isServerError = error instanceof ServerError;
|
|
191
221
|
|
|
@@ -209,7 +239,6 @@ export async function runWithReconnect<TFilter, TBlock>(
|
|
|
209
239
|
}
|
|
210
240
|
}
|
|
211
241
|
}
|
|
212
|
-
|
|
213
242
|
throw error;
|
|
214
243
|
}
|
|
215
244
|
}
|
|
@@ -217,6 +246,7 @@ export async function runWithReconnect<TFilter, TBlock>(
|
|
|
217
246
|
|
|
218
247
|
export interface RunOptions {
|
|
219
248
|
onConnect?: () => void | Promise<void>;
|
|
249
|
+
abortSignal?: AbortSignal;
|
|
220
250
|
}
|
|
221
251
|
|
|
222
252
|
export async function run<TFilter, TBlock>(
|
|
@@ -231,14 +261,16 @@ export async function run<TFilter, TBlock>(
|
|
|
231
261
|
context.debug = true;
|
|
232
262
|
}
|
|
233
263
|
|
|
234
|
-
|
|
264
|
+
const { abortSignal } = runOptions;
|
|
265
|
+
|
|
266
|
+
await indexer.hooks.callHook("plugins:init", { abortSignal });
|
|
235
267
|
|
|
236
|
-
const middleware = await registerMiddleware(indexer);
|
|
268
|
+
const middleware = await registerMiddleware(indexer, abortSignal);
|
|
237
269
|
|
|
238
270
|
const indexerMetrics = createIndexerMetrics();
|
|
239
271
|
const tracer = createTracer();
|
|
240
272
|
|
|
241
|
-
await indexer.hooks.callHook("run:before");
|
|
273
|
+
await indexer.hooks.callHook("run:before", { abortSignal });
|
|
242
274
|
|
|
243
275
|
const { indexerName: indexerId } = useInternalContext();
|
|
244
276
|
|
|
@@ -269,7 +301,11 @@ export async function run<TFilter, TBlock>(
|
|
|
269
301
|
|
|
270
302
|
const options: StreamDataOptions = {};
|
|
271
303
|
|
|
272
|
-
await indexer.hooks.callHook("connect:before", {
|
|
304
|
+
await indexer.hooks.callHook("connect:before", {
|
|
305
|
+
request,
|
|
306
|
+
options,
|
|
307
|
+
abortSignal,
|
|
308
|
+
});
|
|
273
309
|
|
|
274
310
|
// store main filter, so later it can be merged
|
|
275
311
|
let mainFilter: TFilter;
|
|
@@ -282,7 +318,7 @@ export async function run<TFilter, TBlock>(
|
|
|
282
318
|
StreamDataResponse<TBlock>
|
|
283
319
|
> = client.streamData(request, options)[Symbol.asyncIterator]();
|
|
284
320
|
|
|
285
|
-
await indexer.hooks.callHook("connect:after", { request });
|
|
321
|
+
await indexer.hooks.callHook("connect:after", { request, abortSignal });
|
|
286
322
|
|
|
287
323
|
let onConnectCalled = false;
|
|
288
324
|
|
|
@@ -300,7 +336,7 @@ export async function run<TFilter, TBlock>(
|
|
|
300
336
|
}
|
|
301
337
|
}
|
|
302
338
|
|
|
303
|
-
await indexer.hooks.callHook("message", { message });
|
|
339
|
+
await indexer.hooks.callHook("message", { message, abortSignal });
|
|
304
340
|
|
|
305
341
|
switch (message._tag) {
|
|
306
342
|
case "data": {
|
|
@@ -320,6 +356,8 @@ export async function run<TFilter, TBlock>(
|
|
|
320
356
|
},
|
|
321
357
|
);
|
|
322
358
|
|
|
359
|
+
reloadIfNeeded();
|
|
360
|
+
|
|
323
361
|
await middleware(context, async () => {
|
|
324
362
|
let block: TBlock | null;
|
|
325
363
|
|
|
@@ -339,6 +377,7 @@ export async function run<TFilter, TBlock>(
|
|
|
339
377
|
finality,
|
|
340
378
|
production,
|
|
341
379
|
context,
|
|
380
|
+
abortSignal,
|
|
342
381
|
});
|
|
343
382
|
|
|
344
383
|
// write returned data from factory function if filter is not defined
|
|
@@ -360,6 +399,7 @@ export async function run<TFilter, TBlock>(
|
|
|
360
399
|
await indexer.hooks.callHook("connect:factory", {
|
|
361
400
|
request,
|
|
362
401
|
endCursor,
|
|
402
|
+
abortSignal,
|
|
363
403
|
});
|
|
364
404
|
|
|
365
405
|
// create new stream with new request
|
|
@@ -391,6 +431,7 @@ export async function run<TFilter, TBlock>(
|
|
|
391
431
|
finality,
|
|
392
432
|
production,
|
|
393
433
|
context,
|
|
434
|
+
abortSignal,
|
|
394
435
|
});
|
|
395
436
|
|
|
396
437
|
span.end();
|
|
@@ -398,6 +439,8 @@ export async function run<TFilter, TBlock>(
|
|
|
398
439
|
}
|
|
399
440
|
});
|
|
400
441
|
|
|
442
|
+
reloadIfNeeded();
|
|
443
|
+
|
|
401
444
|
span.end();
|
|
402
445
|
});
|
|
403
446
|
|
|
@@ -420,6 +463,7 @@ export async function run<TFilter, TBlock>(
|
|
|
420
463
|
});
|
|
421
464
|
await indexer.hooks.callHook("message:invalidate", {
|
|
422
465
|
message: message.invalidate,
|
|
466
|
+
abortSignal,
|
|
423
467
|
});
|
|
424
468
|
span.end();
|
|
425
469
|
});
|
|
@@ -429,6 +473,7 @@ export async function run<TFilter, TBlock>(
|
|
|
429
473
|
await tracer.startActiveSpan("message finalize", async (span) => {
|
|
430
474
|
await indexer.hooks.callHook("message:finalize", {
|
|
431
475
|
message: message.finalize,
|
|
476
|
+
abortSignal,
|
|
432
477
|
});
|
|
433
478
|
span.end();
|
|
434
479
|
});
|
|
@@ -436,7 +481,11 @@ export async function run<TFilter, TBlock>(
|
|
|
436
481
|
}
|
|
437
482
|
case "heartbeat": {
|
|
438
483
|
await tracer.startActiveSpan("message heartbeat", async (span) => {
|
|
439
|
-
|
|
484
|
+
reloadIfNeeded();
|
|
485
|
+
|
|
486
|
+
await indexer.hooks.callHook("message:heartbeat", { abortSignal });
|
|
487
|
+
reloadIfNeeded();
|
|
488
|
+
|
|
440
489
|
span.end();
|
|
441
490
|
});
|
|
442
491
|
break;
|
|
@@ -460,6 +509,7 @@ export async function run<TFilter, TBlock>(
|
|
|
460
509
|
|
|
461
510
|
await indexer.hooks.callHook("message:systemMessage", {
|
|
462
511
|
message: message.systemMessage,
|
|
512
|
+
abortSignal,
|
|
463
513
|
});
|
|
464
514
|
span.end();
|
|
465
515
|
},
|
|
@@ -471,21 +521,22 @@ export async function run<TFilter, TBlock>(
|
|
|
471
521
|
throw new Error("not implemented");
|
|
472
522
|
}
|
|
473
523
|
}
|
|
474
|
-
|
|
475
|
-
await indexer.hooks.callHook("run:after");
|
|
476
524
|
}
|
|
525
|
+
|
|
526
|
+
await indexer.hooks.callHook("run:after", { abortSignal });
|
|
477
527
|
});
|
|
478
528
|
}
|
|
479
529
|
|
|
480
530
|
async function registerMiddleware<TFilter, TBlock>(
|
|
481
531
|
indexer: Indexer<TFilter, TBlock>,
|
|
532
|
+
abortSignal?: AbortSignal,
|
|
482
533
|
): Promise<MiddlewareFunction<IndexerContext>> {
|
|
483
534
|
const middleware: MiddlewareFunction<IndexerContext>[] = [];
|
|
484
535
|
const use = (fn: MiddlewareFunction<IndexerContext>) => {
|
|
485
536
|
middleware.push(fn);
|
|
486
537
|
};
|
|
487
538
|
|
|
488
|
-
await indexer.hooks.callHook("handler:middleware", { use });
|
|
539
|
+
await indexer.hooks.callHook("handler:middleware", { use, abortSignal });
|
|
489
540
|
|
|
490
541
|
const composed = compose(middleware);
|
|
491
542
|
|
package/src/internal/testing.ts
CHANGED
|
@@ -10,15 +10,19 @@ import { type IndexerConfig, createIndexer, defineIndexer } from "../indexer";
|
|
|
10
10
|
import { defineIndexerPlugin, logger } from "../plugins";
|
|
11
11
|
import { type InternalContext, internalContext } from "./plugins";
|
|
12
12
|
|
|
13
|
+
export type InvalidateConfig = {
|
|
14
|
+
invalidateFromIndex: number;
|
|
15
|
+
invalidateTriggerIndex: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type FinalizeConfig = {
|
|
19
|
+
finalizeToIndex: number;
|
|
20
|
+
finalizeTriggerIndex: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
13
23
|
export type MockMessagesOptions = {
|
|
14
|
-
invalidate?:
|
|
15
|
-
|
|
16
|
-
invalidateTriggerIndex: number;
|
|
17
|
-
};
|
|
18
|
-
finalize?: {
|
|
19
|
-
finalizeToIndex: number;
|
|
20
|
-
finalizeTriggerIndex: number;
|
|
21
|
-
};
|
|
24
|
+
invalidate?: InvalidateConfig | InvalidateConfig[];
|
|
25
|
+
finalize?: FinalizeConfig | FinalizeConfig[];
|
|
22
26
|
uniqueKey?: boolean;
|
|
23
27
|
baseBlockNumber?: bigint;
|
|
24
28
|
};
|
|
@@ -27,18 +31,35 @@ export function generateMockMessages(
|
|
|
27
31
|
count = 10,
|
|
28
32
|
options?: MockMessagesOptions,
|
|
29
33
|
): MockStreamResponse[] {
|
|
30
|
-
const invalidateAt = options?.invalidate;
|
|
31
|
-
const finalizeAt = options?.finalize;
|
|
32
34
|
const messages: MockStreamResponse[] = [];
|
|
33
|
-
|
|
34
35
|
const baseBlockNumber = options?.baseBlockNumber ?? BigInt(5_000_000);
|
|
35
36
|
|
|
37
|
+
const invalidateConfigs = options?.invalidate
|
|
38
|
+
? Array.isArray(options.invalidate)
|
|
39
|
+
? options.invalidate
|
|
40
|
+
: [options.invalidate]
|
|
41
|
+
: [];
|
|
42
|
+
|
|
43
|
+
const finalizeConfigs = options?.finalize
|
|
44
|
+
? Array.isArray(options.finalize)
|
|
45
|
+
? options.finalize
|
|
46
|
+
: [options.finalize]
|
|
47
|
+
: [];
|
|
48
|
+
|
|
36
49
|
for (let i = 0; i < count; i++) {
|
|
37
50
|
const currentBlockNumber = baseBlockNumber + BigInt(i);
|
|
38
51
|
const uniqueKey = uniqueKeyFromOrderKey(currentBlockNumber);
|
|
39
|
-
|
|
52
|
+
|
|
53
|
+
const invalidateConfig = invalidateConfigs.find(
|
|
54
|
+
(cfg) => cfg.invalidateTriggerIndex === i,
|
|
55
|
+
);
|
|
56
|
+
const finalizeConfig = finalizeConfigs.find(
|
|
57
|
+
(cfg) => cfg.finalizeTriggerIndex === i,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (invalidateConfig) {
|
|
40
61
|
const invalidateToBlock =
|
|
41
|
-
baseBlockNumber + BigInt(
|
|
62
|
+
baseBlockNumber + BigInt(invalidateConfig.invalidateFromIndex);
|
|
42
63
|
messages.push({
|
|
43
64
|
_tag: "invalidate",
|
|
44
65
|
invalidate: {
|
|
@@ -50,16 +71,16 @@ export function generateMockMessages(
|
|
|
50
71
|
},
|
|
51
72
|
} as Invalidate,
|
|
52
73
|
});
|
|
53
|
-
} else if (
|
|
54
|
-
const
|
|
55
|
-
baseBlockNumber + BigInt(
|
|
74
|
+
} else if (finalizeConfig) {
|
|
75
|
+
const finalizedToBlock =
|
|
76
|
+
baseBlockNumber + BigInt(finalizeConfig.finalizeToIndex);
|
|
56
77
|
messages.push({
|
|
57
78
|
_tag: "finalize",
|
|
58
79
|
finalize: {
|
|
59
80
|
cursor: {
|
|
60
|
-
orderKey:
|
|
81
|
+
orderKey: finalizedToBlock,
|
|
61
82
|
uniqueKey: options?.uniqueKey
|
|
62
|
-
? uniqueKeyFromOrderKey(
|
|
83
|
+
? uniqueKeyFromOrderKey(finalizedToBlock)
|
|
63
84
|
: undefined,
|
|
64
85
|
},
|
|
65
86
|
} as Finalize,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useIndexerContext } from "../context";
|
|
2
|
+
|
|
3
|
+
export function reloadIndexer() {
|
|
4
|
+
const context = useIndexerContext();
|
|
5
|
+
context._reload = true;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function reloadIfNeeded() {
|
|
9
|
+
const context = useIndexerContext();
|
|
10
|
+
if (context._reload) {
|
|
11
|
+
context._reload = false;
|
|
12
|
+
throw new ReloadIndexerRequest();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ReloadIndexerRequest extends Error {
|
|
17
|
+
constructor(message?: string) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "ReloadIndexerRequest";
|
|
20
|
+
}
|
|
21
|
+
}
|