envio 3.2.0 → 3.3.0-alpha.0
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/package.json +6 -7
- package/src/Batch.res +12 -15
- package/src/Batch.res.mjs +4 -5
- package/src/BatchProcessing.res +199 -0
- package/src/BatchProcessing.res.mjs +125 -0
- package/src/ChainFetching.res +375 -0
- package/src/ChainFetching.res.mjs +206 -0
- package/src/ChainMetadata.res +27 -0
- package/src/ChainMetadata.res.mjs +27 -0
- package/src/ChainState.res +618 -0
- package/src/ChainState.res.mjs +461 -0
- package/src/ChainState.resi +85 -0
- package/src/Config.res +13 -4
- package/src/Config.res.mjs +8 -3
- package/src/ContractRegisterContext.res +106 -0
- package/src/ContractRegisterContext.res.mjs +76 -0
- package/src/Core.res +3 -0
- package/src/CrossChainState.res +269 -0
- package/src/CrossChainState.res.mjs +197 -0
- package/src/CrossChainState.resi +47 -0
- package/src/Ecosystem.res +58 -0
- package/src/Ecosystem.res.mjs +43 -1
- package/src/Env.res +7 -2
- package/src/Env.res.mjs +5 -2
- package/src/EventConfigBuilder.res +35 -0
- package/src/EventConfigBuilder.res.mjs +21 -0
- package/src/EventProcessing.res +60 -46
- package/src/EventProcessing.res.mjs +33 -32
- package/src/EventUtils.res +0 -4
- package/src/EventUtils.res.mjs +0 -4
- package/src/ExitOnCaughtUp.res +10 -0
- package/src/ExitOnCaughtUp.res.mjs +22 -0
- package/src/FetchState.res +162 -113
- package/src/FetchState.res.mjs +181 -119
- package/src/HandlerLoader.res +6 -1
- package/src/HandlerLoader.res.mjs +13 -36
- package/src/InMemoryStore.res +36 -451
- package/src/InMemoryStore.res.mjs +20 -369
- package/src/IndexerLoop.res +44 -0
- package/src/IndexerLoop.res.mjs +46 -0
- package/src/IndexerState.res +544 -0
- package/src/IndexerState.res.mjs +547 -0
- package/src/IndexerState.resi +132 -0
- package/src/Internal.res +44 -7
- package/src/LoadLayer.res +20 -18
- package/src/LoadLayer.res.mjs +14 -12
- package/src/LoadLayer.resi +6 -3
- package/src/LogSelection.res +86 -17
- package/src/LogSelection.res.mjs +67 -14
- package/src/Logging.res +11 -44
- package/src/Logging.res.mjs +10 -42
- package/src/Main.res +54 -79
- package/src/Main.res.mjs +44 -56
- package/src/PgStorage.res +8 -71
- package/src/PgStorage.res.mjs +3 -47
- package/src/Prometheus.res +7 -8
- package/src/Prometheus.res.mjs +7 -4
- package/src/PruneStaleHistory.res +45 -0
- package/src/PruneStaleHistory.res.mjs +46 -0
- package/src/RawEvent.res +73 -0
- package/src/RawEvent.res.mjs +51 -0
- package/src/Rollback.res +204 -0
- package/src/Rollback.res.mjs +118 -0
- package/src/SimulateItems.res +12 -10
- package/src/SimulateItems.res.mjs +1 -1
- package/src/TestIndexer.res +34 -27
- package/src/TestIndexer.res.mjs +4 -1
- package/src/UserContext.res +26 -114
- package/src/UserContext.res.mjs +15 -78
- package/src/Writing.res +242 -0
- package/src/Writing.res.mjs +215 -0
- package/src/db/InternalTable.res +14 -27
- package/src/sources/Evm.res +40 -1
- package/src/sources/Evm.res.mjs +94 -84
- package/src/sources/Fuel.res +40 -1
- package/src/sources/Fuel.res.mjs +36 -26
- package/src/sources/HyperFuel.res +41 -120
- package/src/sources/HyperFuel.res.mjs +42 -80
- package/src/sources/HyperFuel.resi +1 -24
- package/src/sources/HyperFuelClient.res +16 -297
- package/src/sources/HyperFuelClient.res.mjs +5 -4
- package/src/sources/HyperFuelSource.res +33 -8
- package/src/sources/HyperFuelSource.res.mjs +56 -10
- package/src/sources/HyperSyncSource.res +7 -5
- package/src/sources/HyperSyncSource.res.mjs +3 -3
- package/src/sources/RpcSource.res +2 -2
- package/src/sources/RpcSource.res.mjs +1 -1
- package/src/sources/SourceManager.res +8 -18
- package/src/sources/SourceManager.res.mjs +8 -5
- package/src/sources/SourceManager.resi +4 -1
- package/src/sources/Svm.res +18 -1
- package/src/sources/Svm.res.mjs +30 -22
- package/src/sources/SvmHyperSyncSource.res +1 -1
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/src/tui/Tui.res +38 -36
- package/src/tui/Tui.res.mjs +51 -51
- package/src/ChainFetcher.res +0 -519
- package/src/ChainFetcher.res.mjs +0 -314
- package/src/ChainManager.res +0 -358
- package/src/ChainManager.res.mjs +0 -291
- package/src/Ctx.res +0 -6
- package/src/Ctx.res.mjs +0 -2
- package/src/GlobalState.res +0 -1056
- package/src/GlobalState.res.mjs +0 -1086
- package/src/GlobalStateManager.res +0 -57
- package/src/GlobalStateManager.res.mjs +0 -68
- package/src/GlobalStateManager.resi +0 -7
- package/src/Ports.res +0 -5
- package/src/Ports.res.mjs +0 -9
- package/src/adapters/MarkBatchProcessedAdapter.res +0 -5
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +0 -14
- package/src/sources/EnvioApiClient.res +0 -15
- package/src/sources/EnvioApiClient.res.mjs +0 -24
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Whole-indexer view over every chain's ChainState. `t` is opaque: other modules
|
|
2
|
+
// read it through the accessors and change it only through the transitions here.
|
|
3
|
+
|
|
4
|
+
type t
|
|
5
|
+
|
|
6
|
+
let calculateTargetBufferSize: unit => int
|
|
7
|
+
|
|
8
|
+
let make: (
|
|
9
|
+
~chainStates: dict<ChainState.t>,
|
|
10
|
+
~isInReorgThreshold: bool,
|
|
11
|
+
~isRealtime: bool,
|
|
12
|
+
~maxBackfillConcurrency: int=?,
|
|
13
|
+
~maxRealtimeConcurrency: int=?,
|
|
14
|
+
~targetBufferSize: int=?,
|
|
15
|
+
) => t
|
|
16
|
+
|
|
17
|
+
// Accessors.
|
|
18
|
+
let chainStates: t => dict<ChainState.t>
|
|
19
|
+
let isRealtime: t => bool
|
|
20
|
+
let isInReorgThreshold: t => bool
|
|
21
|
+
let maxConcurrency: t => int
|
|
22
|
+
let inFlight: t => int
|
|
23
|
+
|
|
24
|
+
// Derived (pure).
|
|
25
|
+
let nextItemIsNone: t => bool
|
|
26
|
+
let getSafeCheckpointId: t => option<Internal.checkpointId>
|
|
27
|
+
|
|
28
|
+
// Cross-chain transitions.
|
|
29
|
+
let createBatch: (
|
|
30
|
+
t,
|
|
31
|
+
~processedCheckpointId: Internal.checkpointId,
|
|
32
|
+
~batchSizeTarget: int,
|
|
33
|
+
~isRollback: bool,
|
|
34
|
+
) => Batch.t
|
|
35
|
+
let enterReorgThreshold: t => unit
|
|
36
|
+
let applyBatchProgress: (t, ~batch: Batch.t) => unit
|
|
37
|
+
|
|
38
|
+
// Fetch control.
|
|
39
|
+
let priorityOrder: t => array<ChainState.t>
|
|
40
|
+
let checkAndFetch: (
|
|
41
|
+
t,
|
|
42
|
+
~fetchChain: (
|
|
43
|
+
~chain: ChainMap.Chain.t,
|
|
44
|
+
~concurrencyLimit: int,
|
|
45
|
+
~bufferLimit: int,
|
|
46
|
+
) => promise<unit>,
|
|
47
|
+
) => promise<unit>
|
package/src/Ecosystem.res
CHANGED
|
@@ -29,8 +29,66 @@ type t = {
|
|
|
29
29
|
`LogSelection.res`. SVM does not support event handlers, so its
|
|
30
30
|
schema always surfaces `None`. */
|
|
31
31
|
onEventBlockFilterSchema: S.t<option<unknown>>,
|
|
32
|
+
/** Base logger injected at construction. Used to build per-item child
|
|
33
|
+
loggers (see `getItemLogger`). */
|
|
34
|
+
logger: Pino.t,
|
|
35
|
+
/** Materialise the user-facing event handed to handlers and contract
|
|
36
|
+
registration from an item's opaque payload. */
|
|
37
|
+
toEvent: Internal.eventItem => Internal.event,
|
|
38
|
+
/** Build the per-item child logger for an event item, with
|
|
39
|
+
ecosystem-specific log fields (EVM/Fuel: contract/event/address; SVM:
|
|
40
|
+
program/instruction/programId). Closes over the injected logger. */
|
|
41
|
+
toEventLogger: Internal.eventItem => Pino.t,
|
|
42
|
+
/** Build a raw event row for the `raw_events` table. Unsupported on SVM,
|
|
43
|
+
where the implementation throws. */
|
|
44
|
+
toRawEvent: Internal.eventItem => Internal.rawEvent,
|
|
32
45
|
}
|
|
33
46
|
|
|
47
|
+
// The materialised event and the child logger are both memoised on the item
|
|
48
|
+
// object (an item is processed across preload + execution passes, and logged
|
|
49
|
+
// from several places). Hidden keys mirror each other.
|
|
50
|
+
let getItemEvent = {
|
|
51
|
+
let cacheKey = "_event"
|
|
52
|
+
(item: Internal.item, ~ecosystem: t): Internal.event => {
|
|
53
|
+
let cache = item->(Utils.magic: Internal.item => dict<Internal.event>)
|
|
54
|
+
switch cache->Utils.Dict.dangerouslyGetNonOption(cacheKey) {
|
|
55
|
+
| Some(event) => event
|
|
56
|
+
| None =>
|
|
57
|
+
let event = ecosystem.toEvent(item->Internal.castUnsafeEventItem)
|
|
58
|
+
cache->Dict.set(cacheKey, event)
|
|
59
|
+
event
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let getItemLogger = {
|
|
65
|
+
let cacheKey = "_logger"
|
|
66
|
+
(item: Internal.item, ~ecosystem: t): Pino.t => {
|
|
67
|
+
let cache = item->(Utils.magic: Internal.item => dict<Pino.t>)
|
|
68
|
+
switch cache->Utils.Dict.dangerouslyGetNonOption(cacheKey) {
|
|
69
|
+
| Some(logger) => logger
|
|
70
|
+
| None =>
|
|
71
|
+
let logger = switch item {
|
|
72
|
+
| Internal.Event(_) => ecosystem.toEventLogger(item->Internal.castUnsafeEventItem)
|
|
73
|
+
| Block({blockNumber, onBlockConfig}) =>
|
|
74
|
+
Logging.createChildFrom(
|
|
75
|
+
~logger=ecosystem.logger,
|
|
76
|
+
~params={
|
|
77
|
+
"onBlock": onBlockConfig.name,
|
|
78
|
+
"chainId": onBlockConfig.chainId,
|
|
79
|
+
"block": blockNumber,
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
cache->Dict.set(cacheKey, logger)
|
|
84
|
+
logger
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let getItemUserLogger = (item: Internal.item, ~ecosystem: t): Envio.logger =>
|
|
90
|
+
getItemLogger(item, ~ecosystem)->Logging.userLogger
|
|
91
|
+
|
|
34
92
|
let makeOnBlockArgs = (~blockNumber: int, ~ecosystem: t, ~context): Internal.onBlockArgs => {
|
|
35
93
|
switch ecosystem.name {
|
|
36
94
|
| Svm => {slot: blockNumber, context}
|
package/src/Ecosystem.res.mjs
CHANGED
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Logging from "./Logging.res.mjs";
|
|
3
4
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
4
5
|
|
|
6
|
+
let cacheKey = "_event";
|
|
7
|
+
|
|
8
|
+
function getItemEvent(item, ecosystem) {
|
|
9
|
+
let event = item[cacheKey];
|
|
10
|
+
if (event !== undefined) {
|
|
11
|
+
return Primitive_option.valFromOption(event);
|
|
12
|
+
}
|
|
13
|
+
let event$1 = ecosystem.toEvent(item);
|
|
14
|
+
item[cacheKey] = event$1;
|
|
15
|
+
return event$1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let cacheKey$1 = "_logger";
|
|
19
|
+
|
|
20
|
+
function getItemLogger(item, ecosystem) {
|
|
21
|
+
let logger = item[cacheKey$1];
|
|
22
|
+
if (logger !== undefined) {
|
|
23
|
+
return logger;
|
|
24
|
+
}
|
|
25
|
+
let logger$1;
|
|
26
|
+
if (item.kind === 0) {
|
|
27
|
+
logger$1 = ecosystem.toEventLogger(item);
|
|
28
|
+
} else {
|
|
29
|
+
let onBlockConfig = item.onBlockConfig;
|
|
30
|
+
logger$1 = Logging.createChildFrom(ecosystem.logger, {
|
|
31
|
+
onBlock: onBlockConfig.name,
|
|
32
|
+
chainId: onBlockConfig.chainId,
|
|
33
|
+
block: item.blockNumber
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
item[cacheKey$1] = logger$1;
|
|
37
|
+
return logger$1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getItemUserLogger(item, ecosystem) {
|
|
41
|
+
return Logging.userLogger(getItemLogger(item, ecosystem));
|
|
42
|
+
}
|
|
43
|
+
|
|
5
44
|
function makeOnBlockArgs(blockNumber, ecosystem, context) {
|
|
6
45
|
let match = ecosystem.name;
|
|
7
46
|
switch (match) {
|
|
@@ -23,6 +62,9 @@ function makeOnBlockArgs(blockNumber, ecosystem, context) {
|
|
|
23
62
|
}
|
|
24
63
|
|
|
25
64
|
export {
|
|
65
|
+
getItemEvent,
|
|
66
|
+
getItemLogger,
|
|
67
|
+
getItemUserLogger,
|
|
26
68
|
makeOnBlockArgs,
|
|
27
69
|
}
|
|
28
|
-
/*
|
|
70
|
+
/* Logging Not a pure module */
|
package/src/Env.res
CHANGED
|
@@ -8,8 +8,13 @@ let updateSyncTimeOnRestart =
|
|
|
8
8
|
envSafe->EnvSafe.get("UPDATE_SYNC_TIME_ON_RESTART", S.bool, ~fallback=true)
|
|
9
9
|
let targetBufferSize = envSafe->EnvSafe.get("ENVIO_INDEXING_MAX_BUFFER_SIZE", S.option(S.int))
|
|
10
10
|
let maxAddrInPartition = envSafe->EnvSafe.get("MAX_PARTITION_SIZE", S.int, ~fallback=5_000)
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
// Global caps on concurrent data-source queries across the whole indexer (all
|
|
12
|
+
// chains share the budget), not per chain. Realtime allows far more since head
|
|
13
|
+
// queries are small and many chains follow the head at once.
|
|
14
|
+
let maxBackfillConcurrency =
|
|
15
|
+
envSafe->EnvSafe.get("ENVIO_MAX_BACKFILL_CONCURRENCY", S.int, ~fallback=30)
|
|
16
|
+
let maxRealtimeConcurrency =
|
|
17
|
+
envSafe->EnvSafe.get("ENVIO_MAX_REALTIME_CONCURRENCY", S.int, ~fallback=200)
|
|
13
18
|
|
|
14
19
|
// Target number of in-memory objects (uncommitted entity/effect changes plus
|
|
15
20
|
// unwritten batch items) the store holds before processing waits for the write
|
package/src/Env.res.mjs
CHANGED
|
@@ -19,7 +19,9 @@ let targetBufferSize = EnvSafe.get(envSafe, "ENVIO_INDEXING_MAX_BUFFER_SIZE", S$
|
|
|
19
19
|
|
|
20
20
|
let maxAddrInPartition = EnvSafe.get(envSafe, "MAX_PARTITION_SIZE", S$RescriptSchema.int, undefined, 5000, undefined, undefined);
|
|
21
21
|
|
|
22
|
-
let
|
|
22
|
+
let maxBackfillConcurrency = EnvSafe.get(envSafe, "ENVIO_MAX_BACKFILL_CONCURRENCY", S$RescriptSchema.int, undefined, 30, undefined, undefined);
|
|
23
|
+
|
|
24
|
+
let maxRealtimeConcurrency = EnvSafe.get(envSafe, "ENVIO_MAX_REALTIME_CONCURRENCY", S$RescriptSchema.int, undefined, 200, undefined, undefined);
|
|
23
25
|
|
|
24
26
|
let inMemoryObjectsTarget = EnvSafe.get(envSafe, "ENVIO_IN_MEMORY_OBJECTS_TARGET", S$RescriptSchema.int, undefined, 100000, undefined, undefined);
|
|
25
27
|
|
|
@@ -222,7 +224,8 @@ export {
|
|
|
222
224
|
updateSyncTimeOnRestart,
|
|
223
225
|
targetBufferSize,
|
|
224
226
|
maxAddrInPartition,
|
|
225
|
-
|
|
227
|
+
maxBackfillConcurrency,
|
|
228
|
+
maxRealtimeConcurrency,
|
|
226
229
|
inMemoryObjectsTarget,
|
|
227
230
|
serverPort,
|
|
228
231
|
tuiEnvVar,
|
|
@@ -309,6 +309,39 @@ let resolveFieldSelection = (
|
|
|
309
309
|
(selectedBlockFields, selectedTransactionFields)
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
// ============== Client-side address filter ==============
|
|
313
|
+
|
|
314
|
+
let compileAddressFilter: string => (
|
|
315
|
+
Internal.eventPayload,
|
|
316
|
+
int,
|
|
317
|
+
dict<Internal.indexingContract>,
|
|
318
|
+
) => bool = %raw(`function (body) {
|
|
319
|
+
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
320
|
+
}`)
|
|
321
|
+
|
|
322
|
+
// Body of the client-side address filter for a DNF of address-filtered param
|
|
323
|
+
// names (OR of AND-groups): keep the event only if some group's params are all
|
|
324
|
+
// registered at or before the log's block. The DNF is fixed here, so it's
|
|
325
|
+
// unrolled into one boolean expression — no per-event closure, loop, or array.
|
|
326
|
+
// `None` when there's no address-param filter. Exposed for snapshotting.
|
|
327
|
+
let buildAddressFilterBody = (groups: array<array<string>>): option<string> => {
|
|
328
|
+
switch groups {
|
|
329
|
+
| [] => None
|
|
330
|
+
| _ =>
|
|
331
|
+
let leaf = name =>
|
|
332
|
+
`(ic = indexingAddresses[p[${JSON.stringify(
|
|
333
|
+
JSON.String(name),
|
|
334
|
+
)}]]) !== undefined && ic.effectiveStartBlock <= blockNumber`
|
|
335
|
+
let groupExprs =
|
|
336
|
+
groups->Array.map(group => "(" ++ group->Array.map(leaf)->Array.join(" && ") ++ ")")
|
|
337
|
+
Some("var p = event.params, ic; return " ++ groupExprs->Array.join(" || ") ++ ";")
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
let buildAddressFilter = (groups: array<array<string>>): option<
|
|
342
|
+
(Internal.eventPayload, int, dict<Internal.indexingContract>) => bool,
|
|
343
|
+
> => buildAddressFilterBody(groups)->Option.map(compileAddressFilter)
|
|
344
|
+
|
|
312
345
|
// ============== Build complete EVM event config ==============
|
|
313
346
|
|
|
314
347
|
let buildEvmEventConfig = (
|
|
@@ -334,6 +367,7 @@ let buildEvmEventConfig = (
|
|
|
334
367
|
let {
|
|
335
368
|
getEventFiltersOrThrow,
|
|
336
369
|
filterByAddresses,
|
|
370
|
+
addressFilterParamGroups,
|
|
337
371
|
startBlock: whereStartBlock,
|
|
338
372
|
} = LogSelection.parseEventFiltersOrThrow(
|
|
339
373
|
~eventFilters,
|
|
@@ -374,6 +408,7 @@ let buildEvmEventConfig = (
|
|
|
374
408
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
375
409
|
getEventFiltersOrThrow,
|
|
376
410
|
filterByAddresses,
|
|
411
|
+
clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups),
|
|
377
412
|
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
378
413
|
startBlock: resolvedStartBlock,
|
|
379
414
|
selectedBlockFields,
|
|
@@ -251,6 +251,23 @@ function resolveFieldSelection(blockFields, transactionFields, globalBlockFields
|
|
|
251
251
|
];
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
let compileAddressFilter = (function (body) {
|
|
255
|
+
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
function buildAddressFilterBody(groups) {
|
|
259
|
+
if (groups.length === 0) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
let leaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
263
|
+
let groupExprs = groups.map(group => "(" + group.map(leaf).join(" && ") + ")");
|
|
264
|
+
return "var p = event.params, ic; return " + groupExprs.join(" || ") + ";";
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function buildAddressFilter(groups) {
|
|
268
|
+
return Stdlib_Option.map(buildAddressFilterBody(groups), compileAddressFilter);
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcard, handler, contractRegister, eventFilters, probeChainId, onEventBlockFilterSchema, blockFields, transactionFields, startBlock, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
|
|
255
272
|
let globalBlockFieldsSet = globalBlockFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalBlockFieldsSetOpt) : new Set();
|
|
256
273
|
let globalTransactionFieldsSet = globalTransactionFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalTransactionFieldsSetOpt) : new Set();
|
|
@@ -274,6 +291,7 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
|
|
|
274
291
|
isWildcard: isWildcard,
|
|
275
292
|
filterByAddresses: filterByAddresses,
|
|
276
293
|
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
294
|
+
clientAddressFilter: Stdlib_Option.map(buildAddressFilterBody(match.addressFilterParamGroups), compileAddressFilter),
|
|
277
295
|
handler: handler,
|
|
278
296
|
contractRegister: contractRegister,
|
|
279
297
|
paramsRawEventSchema: buildParamsSchema(params),
|
|
@@ -393,6 +411,9 @@ export {
|
|
|
393
411
|
buildTopicGetter,
|
|
394
412
|
alwaysIncludedBlockFields,
|
|
395
413
|
resolveFieldSelection,
|
|
414
|
+
compileAddressFilter,
|
|
415
|
+
buildAddressFilterBody,
|
|
416
|
+
buildAddressFilter,
|
|
396
417
|
buildEvmEventConfig,
|
|
397
418
|
buildSvmInstructionEventConfig,
|
|
398
419
|
buildFuelEventConfig,
|
package/src/EventProcessing.res
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
let allChainsEventsProcessedToEndblock = (
|
|
2
|
-
|
|
3
|
-
->
|
|
4
|
-
->Array.every(
|
|
1
|
+
let allChainsEventsProcessedToEndblock = (chainStates: dict<ChainState.t>) => {
|
|
2
|
+
chainStates
|
|
3
|
+
->Dict.valuesToArray
|
|
4
|
+
->Array.every(cs => cs->ChainState.hasProcessedToEndblock)
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
let computeChainsState = (
|
|
7
|
+
let computeChainsState = (chainStates: dict<ChainState.t>): Internal.chains => {
|
|
8
8
|
let chains = Dict.make()
|
|
9
9
|
|
|
10
|
-
let
|
|
10
|
+
let values = chainStates->Dict.valuesToArray
|
|
11
|
+
let isRealtime = values->Array.every(cs => cs->ChainState.isReady)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
->Array.forEach(chain => {
|
|
15
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
13
|
+
values->Array.forEach(cs => {
|
|
14
|
+
let chainId = (cs->ChainState.chainConfig).id
|
|
16
15
|
chains->Dict.set(
|
|
17
16
|
chainId->Int.toString,
|
|
18
17
|
{
|
|
@@ -31,7 +30,7 @@ let runEventHandlerOrThrow = async (
|
|
|
31
30
|
item: Internal.item,
|
|
32
31
|
~checkpointId,
|
|
33
32
|
~handler,
|
|
34
|
-
~
|
|
33
|
+
~indexerState,
|
|
35
34
|
~loadManager,
|
|
36
35
|
~persistence,
|
|
37
36
|
~chains: Internal.chains,
|
|
@@ -46,7 +45,7 @@ let runEventHandlerOrThrow = async (
|
|
|
46
45
|
let contextParams: UserContext.contextParams = {
|
|
47
46
|
item,
|
|
48
47
|
checkpointId,
|
|
49
|
-
|
|
48
|
+
indexerState,
|
|
50
49
|
loadManager,
|
|
51
50
|
persistence,
|
|
52
51
|
isPreload: false,
|
|
@@ -57,7 +56,7 @@ let runEventHandlerOrThrow = async (
|
|
|
57
56
|
await handler(
|
|
58
57
|
(
|
|
59
58
|
{
|
|
60
|
-
event:
|
|
59
|
+
event: item->Ecosystem.getItemEvent(~ecosystem=config.ecosystem),
|
|
61
60
|
context: UserContext.getHandlerContext(contextParams),
|
|
62
61
|
}: Internal.handlerArgs
|
|
63
62
|
),
|
|
@@ -84,9 +83,10 @@ let runEventHandlerOrThrow = async (
|
|
|
84
83
|
let runHandlerOrThrow = async (
|
|
85
84
|
item: Internal.item,
|
|
86
85
|
~checkpointId,
|
|
87
|
-
~
|
|
86
|
+
~indexerState,
|
|
88
87
|
~loadManager,
|
|
89
|
-
~
|
|
88
|
+
~persistence: Persistence.t,
|
|
89
|
+
~config: Config.t,
|
|
90
90
|
~chains: Internal.chains,
|
|
91
91
|
) => {
|
|
92
92
|
switch item {
|
|
@@ -94,19 +94,19 @@ let runHandlerOrThrow = async (
|
|
|
94
94
|
try {
|
|
95
95
|
let contextParams: UserContext.contextParams = {
|
|
96
96
|
item,
|
|
97
|
-
|
|
97
|
+
indexerState,
|
|
98
98
|
loadManager,
|
|
99
|
-
persistence
|
|
99
|
+
persistence,
|
|
100
100
|
checkpointId,
|
|
101
101
|
isPreload: false,
|
|
102
102
|
chains,
|
|
103
|
-
config
|
|
103
|
+
config,
|
|
104
104
|
isResolved: false,
|
|
105
105
|
}
|
|
106
106
|
await handler(
|
|
107
107
|
Ecosystem.makeOnBlockArgs(
|
|
108
108
|
~blockNumber,
|
|
109
|
-
~ecosystem=
|
|
109
|
+
~ecosystem=config.ecosystem,
|
|
110
110
|
~context=UserContext.getHandlerContext(contextParams),
|
|
111
111
|
),
|
|
112
112
|
)
|
|
@@ -121,16 +121,17 @@ let runHandlerOrThrow = async (
|
|
|
121
121
|
}),
|
|
122
122
|
)
|
|
123
123
|
}
|
|
124
|
-
| Event({eventConfig}) =>
|
|
124
|
+
| Event({eventConfig}) =>
|
|
125
|
+
switch eventConfig.handler {
|
|
125
126
|
| Some(handler) =>
|
|
126
127
|
await item->runEventHandlerOrThrow(
|
|
127
128
|
~handler,
|
|
128
129
|
~checkpointId,
|
|
129
|
-
~
|
|
130
|
+
~indexerState,
|
|
130
131
|
~loadManager,
|
|
131
|
-
~persistence
|
|
132
|
+
~persistence,
|
|
132
133
|
~chains,
|
|
133
|
-
~config
|
|
134
|
+
~config,
|
|
134
135
|
)
|
|
135
136
|
| None => ()
|
|
136
137
|
}
|
|
@@ -142,7 +143,7 @@ let preloadBatchOrThrow = async (
|
|
|
142
143
|
~loadManager,
|
|
143
144
|
~persistence,
|
|
144
145
|
~config: Config.t,
|
|
145
|
-
~
|
|
146
|
+
~indexerState,
|
|
146
147
|
~chains: Internal.chains,
|
|
147
148
|
) => {
|
|
148
149
|
// On the first run of loaders, we don't care about the result,
|
|
@@ -160,7 +161,7 @@ let preloadBatchOrThrow = async (
|
|
|
160
161
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
161
162
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
162
163
|
switch item {
|
|
163
|
-
| Event({eventConfig: {handler, contractName, name: eventName}
|
|
164
|
+
| Event({eventConfig: {handler, contractName, name: eventName}}) =>
|
|
164
165
|
switch handler {
|
|
165
166
|
| None => ()
|
|
166
167
|
| Some(handler) =>
|
|
@@ -171,10 +172,10 @@ let preloadBatchOrThrow = async (
|
|
|
171
172
|
)
|
|
172
173
|
promises->Array.push(
|
|
173
174
|
handler({
|
|
174
|
-
event,
|
|
175
|
+
event: item->Ecosystem.getItemEvent(~ecosystem=config.ecosystem),
|
|
175
176
|
context: UserContext.getHandlerContext({
|
|
176
177
|
item,
|
|
177
|
-
|
|
178
|
+
indexerState,
|
|
178
179
|
loadManager,
|
|
179
180
|
persistence,
|
|
180
181
|
checkpointId,
|
|
@@ -208,7 +209,7 @@ let preloadBatchOrThrow = async (
|
|
|
208
209
|
~ecosystem=config.ecosystem,
|
|
209
210
|
~context=UserContext.getHandlerContext({
|
|
210
211
|
item,
|
|
211
|
-
|
|
212
|
+
indexerState,
|
|
212
213
|
loadManager,
|
|
213
214
|
persistence,
|
|
214
215
|
checkpointId,
|
|
@@ -234,9 +235,10 @@ let preloadBatchOrThrow = async (
|
|
|
234
235
|
|
|
235
236
|
let runBatchHandlersOrThrow = async (
|
|
236
237
|
batch: Batch.t,
|
|
237
|
-
~
|
|
238
|
+
~indexerState,
|
|
238
239
|
~loadManager,
|
|
239
|
-
~
|
|
240
|
+
~persistence,
|
|
241
|
+
~config,
|
|
240
242
|
~chains: Internal.chains,
|
|
241
243
|
) => {
|
|
242
244
|
let itemIdx = ref(0)
|
|
@@ -248,7 +250,15 @@ let runBatchHandlersOrThrow = async (
|
|
|
248
250
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
249
251
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
250
252
|
|
|
251
|
-
await runHandlerOrThrow(
|
|
253
|
+
await runHandlerOrThrow(
|
|
254
|
+
item,
|
|
255
|
+
~checkpointId,
|
|
256
|
+
~indexerState,
|
|
257
|
+
~loadManager,
|
|
258
|
+
~persistence,
|
|
259
|
+
~config,
|
|
260
|
+
~chains,
|
|
261
|
+
)
|
|
252
262
|
}
|
|
253
263
|
itemIdx := itemIdx.contents + checkpointEventsProcessed
|
|
254
264
|
}
|
|
@@ -273,14 +283,15 @@ type logPartitionInfo = {
|
|
|
273
283
|
|
|
274
284
|
let processEventBatch = async (
|
|
275
285
|
~batch: Batch.t,
|
|
276
|
-
~
|
|
286
|
+
~indexerState: IndexerState.t,
|
|
277
287
|
~loadManager,
|
|
278
|
-
~
|
|
279
|
-
~
|
|
288
|
+
~persistence: Persistence.t,
|
|
289
|
+
~config: Config.t,
|
|
290
|
+
~chainStates: dict<ChainState.t>,
|
|
280
291
|
) => {
|
|
281
292
|
let totalBatchSize = batch.totalBatchSize
|
|
282
293
|
// Compute chains state for this batch
|
|
283
|
-
let chains: Internal.chains =
|
|
294
|
+
let chains: Internal.chains = chainStates->computeChainsState
|
|
284
295
|
|
|
285
296
|
let logger = Logging.getLogger()
|
|
286
297
|
logger->Logging.childTrace({
|
|
@@ -296,29 +307,29 @@ let processEventBatch = async (
|
|
|
296
307
|
|
|
297
308
|
try {
|
|
298
309
|
// Backpressure: keep processing within keepLatestChangesLimit of the cycle.
|
|
299
|
-
await
|
|
310
|
+
await indexerState->Writing.awaitCapacity
|
|
300
311
|
|
|
301
312
|
let timeRef = Hrtime.makeTimer()
|
|
302
313
|
|
|
303
314
|
if batch.items->Utils.Array.notEmpty {
|
|
304
|
-
await batch->preloadBatchOrThrow(
|
|
305
|
-
~loadManager,
|
|
306
|
-
~persistence=ctx.persistence,
|
|
307
|
-
~inMemoryStore,
|
|
308
|
-
~chains,
|
|
309
|
-
~config=ctx.config,
|
|
310
|
-
)
|
|
315
|
+
await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
|
|
311
316
|
}
|
|
312
317
|
|
|
313
318
|
let elapsedTimeAfterLoaders = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
314
319
|
|
|
315
320
|
if batch.items->Utils.Array.notEmpty {
|
|
316
|
-
await batch->runBatchHandlersOrThrow(
|
|
321
|
+
await batch->runBatchHandlersOrThrow(
|
|
322
|
+
~indexerState,
|
|
323
|
+
~loadManager,
|
|
324
|
+
~persistence,
|
|
325
|
+
~config,
|
|
326
|
+
~chains,
|
|
327
|
+
)
|
|
317
328
|
}
|
|
318
329
|
|
|
319
330
|
let elapsedTimeAfterProcessing = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
320
331
|
|
|
321
|
-
|
|
332
|
+
indexerState->Writing.commitBatch(~batch)
|
|
322
333
|
|
|
323
334
|
let loaderDuration = elapsedTimeAfterLoaders
|
|
324
335
|
let handlerDuration = elapsedTimeAfterProcessing -. loaderDuration
|
|
@@ -329,7 +340,10 @@ let processEventBatch = async (
|
|
|
329
340
|
reason->ErrorHandling.make(~msg=message, ~logger)->Error
|
|
330
341
|
| ProcessingError({message, exn, item}) =>
|
|
331
342
|
exn
|
|
332
|
-
->ErrorHandling.make(
|
|
343
|
+
->ErrorHandling.make(
|
|
344
|
+
~msg=message,
|
|
345
|
+
~logger=Ecosystem.getItemLogger(item, ~ecosystem=config.ecosystem),
|
|
346
|
+
)
|
|
333
347
|
->Error
|
|
334
348
|
| exn => exn->ErrorHandling.make(~msg="Failed processing batch", ~logger)->Error
|
|
335
349
|
}
|