envio 3.2.1 → 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.
Files changed (106) hide show
  1. package/package.json +6 -7
  2. package/src/Batch.res +12 -15
  3. package/src/Batch.res.mjs +4 -5
  4. package/src/BatchProcessing.res +199 -0
  5. package/src/BatchProcessing.res.mjs +125 -0
  6. package/src/ChainFetching.res +375 -0
  7. package/src/ChainFetching.res.mjs +206 -0
  8. package/src/ChainMetadata.res +27 -0
  9. package/src/ChainMetadata.res.mjs +27 -0
  10. package/src/ChainState.res +618 -0
  11. package/src/ChainState.res.mjs +461 -0
  12. package/src/ChainState.resi +85 -0
  13. package/src/Config.res +13 -4
  14. package/src/Config.res.mjs +8 -3
  15. package/src/ContractRegisterContext.res +106 -0
  16. package/src/ContractRegisterContext.res.mjs +76 -0
  17. package/src/Core.res +3 -0
  18. package/src/CrossChainState.res +269 -0
  19. package/src/CrossChainState.res.mjs +197 -0
  20. package/src/CrossChainState.resi +47 -0
  21. package/src/Ecosystem.res +58 -0
  22. package/src/Ecosystem.res.mjs +43 -1
  23. package/src/Env.res +7 -2
  24. package/src/Env.res.mjs +5 -2
  25. package/src/EventConfigBuilder.res +2 -2
  26. package/src/EventProcessing.res +60 -46
  27. package/src/EventProcessing.res.mjs +33 -32
  28. package/src/EventUtils.res +0 -4
  29. package/src/EventUtils.res.mjs +0 -4
  30. package/src/ExitOnCaughtUp.res +10 -0
  31. package/src/ExitOnCaughtUp.res.mjs +22 -0
  32. package/src/FetchState.res +124 -62
  33. package/src/FetchState.res.mjs +159 -93
  34. package/src/InMemoryStore.res +36 -451
  35. package/src/InMemoryStore.res.mjs +20 -369
  36. package/src/IndexerLoop.res +44 -0
  37. package/src/IndexerLoop.res.mjs +46 -0
  38. package/src/IndexerState.res +544 -0
  39. package/src/IndexerState.res.mjs +547 -0
  40. package/src/IndexerState.resi +132 -0
  41. package/src/Internal.res +29 -8
  42. package/src/LoadLayer.res +20 -18
  43. package/src/LoadLayer.res.mjs +14 -12
  44. package/src/LoadLayer.resi +6 -3
  45. package/src/Logging.res +11 -44
  46. package/src/Logging.res.mjs +10 -42
  47. package/src/Main.res +54 -79
  48. package/src/Main.res.mjs +44 -56
  49. package/src/PgStorage.res +8 -71
  50. package/src/PgStorage.res.mjs +3 -47
  51. package/src/Prometheus.res +7 -8
  52. package/src/Prometheus.res.mjs +7 -4
  53. package/src/PruneStaleHistory.res +45 -0
  54. package/src/PruneStaleHistory.res.mjs +46 -0
  55. package/src/RawEvent.res +73 -0
  56. package/src/RawEvent.res.mjs +51 -0
  57. package/src/Rollback.res +204 -0
  58. package/src/Rollback.res.mjs +118 -0
  59. package/src/SimulateItems.res +12 -10
  60. package/src/SimulateItems.res.mjs +1 -1
  61. package/src/UserContext.res +26 -114
  62. package/src/UserContext.res.mjs +15 -78
  63. package/src/Writing.res +242 -0
  64. package/src/Writing.res.mjs +215 -0
  65. package/src/db/InternalTable.res +14 -27
  66. package/src/sources/Evm.res +40 -1
  67. package/src/sources/Evm.res.mjs +94 -84
  68. package/src/sources/Fuel.res +40 -1
  69. package/src/sources/Fuel.res.mjs +36 -26
  70. package/src/sources/HyperFuel.res +41 -120
  71. package/src/sources/HyperFuel.res.mjs +42 -80
  72. package/src/sources/HyperFuel.resi +1 -24
  73. package/src/sources/HyperFuelClient.res +16 -297
  74. package/src/sources/HyperFuelClient.res.mjs +5 -4
  75. package/src/sources/HyperFuelSource.res +33 -8
  76. package/src/sources/HyperFuelSource.res.mjs +56 -10
  77. package/src/sources/HyperSyncSource.res +5 -3
  78. package/src/sources/HyperSyncSource.res.mjs +1 -1
  79. package/src/sources/RpcSource.res +2 -2
  80. package/src/sources/RpcSource.res.mjs +1 -1
  81. package/src/sources/SourceManager.res +8 -18
  82. package/src/sources/SourceManager.res.mjs +8 -5
  83. package/src/sources/SourceManager.resi +4 -1
  84. package/src/sources/Svm.res +18 -1
  85. package/src/sources/Svm.res.mjs +30 -22
  86. package/src/sources/SvmHyperSyncSource.res +1 -1
  87. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  88. package/src/tui/Tui.res +38 -36
  89. package/src/tui/Tui.res.mjs +51 -51
  90. package/src/ChainFetcher.res +0 -519
  91. package/src/ChainFetcher.res.mjs +0 -314
  92. package/src/ChainManager.res +0 -358
  93. package/src/ChainManager.res.mjs +0 -291
  94. package/src/Ctx.res +0 -6
  95. package/src/Ctx.res.mjs +0 -2
  96. package/src/GlobalState.res +0 -1056
  97. package/src/GlobalState.res.mjs +0 -1086
  98. package/src/GlobalStateManager.res +0 -57
  99. package/src/GlobalStateManager.res.mjs +0 -68
  100. package/src/GlobalStateManager.resi +0 -7
  101. package/src/Ports.res +0 -5
  102. package/src/Ports.res.mjs +0 -9
  103. package/src/adapters/MarkBatchProcessedAdapter.res +0 -5
  104. package/src/adapters/MarkBatchProcessedAdapter.res.mjs +0 -14
  105. package/src/sources/EnvioApiClient.res +0 -15
  106. 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}
@@ -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
- /* No side effect */
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
- let maxPartitionConcurrency =
12
- envSafe->EnvSafe.get("ENVIO_MAX_PARTITION_CONCURRENCY", S.int, ~fallback=10)
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 maxPartitionConcurrency = EnvSafe.get(envSafe, "ENVIO_MAX_PARTITION_CONCURRENCY", S$RescriptSchema.int, undefined, 10, undefined, undefined);
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
- maxPartitionConcurrency,
227
+ maxBackfillConcurrency,
228
+ maxRealtimeConcurrency,
226
229
  inMemoryObjectsTarget,
227
230
  serverPort,
228
231
  tuiEnvVar,
@@ -312,7 +312,7 @@ let resolveFieldSelection = (
312
312
  // ============== Client-side address filter ==============
313
313
 
314
314
  let compileAddressFilter: string => (
315
- Internal.event,
315
+ Internal.eventPayload,
316
316
  int,
317
317
  dict<Internal.indexingContract>,
318
318
  ) => bool = %raw(`function (body) {
@@ -339,7 +339,7 @@ let buildAddressFilterBody = (groups: array<array<string>>): option<string> => {
339
339
  }
340
340
 
341
341
  let buildAddressFilter = (groups: array<array<string>>): option<
342
- (Internal.event, int, dict<Internal.indexingContract>) => bool,
342
+ (Internal.eventPayload, int, dict<Internal.indexingContract>) => bool,
343
343
  > => buildAddressFilterBody(groups)->Option.map(compileAddressFilter)
344
344
 
345
345
  // ============== Build complete EVM event config ==============
@@ -1,18 +1,17 @@
1
- let allChainsEventsProcessedToEndblock = (chainFetchers: ChainMap.t<ChainFetcher.t>) => {
2
- chainFetchers
3
- ->ChainMap.values
4
- ->Array.every(cf => cf->ChainFetcher.hasProcessedToEndblock)
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 = (chainFetchers: ChainMap.t<ChainFetcher.t>): Internal.chains => {
7
+ let computeChainsState = (chainStates: dict<ChainState.t>): Internal.chains => {
8
8
  let chains = Dict.make()
9
9
 
10
- let isRealtime = chainFetchers->ChainMap.values->Array.every(cf => cf->ChainFetcher.isReady)
10
+ let values = chainStates->Dict.valuesToArray
11
+ let isRealtime = values->Array.every(cs => cs->ChainState.isReady)
11
12
 
12
- chainFetchers
13
- ->ChainMap.keys
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
- ~inMemoryStore,
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
- inMemoryStore,
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: eventItem.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
- ~inMemoryStore,
86
+ ~indexerState,
88
87
  ~loadManager,
89
- ~ctx: Ctx.t,
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
- inMemoryStore,
97
+ indexerState,
98
98
  loadManager,
99
- persistence: ctx.persistence,
99
+ persistence,
100
100
  checkpointId,
101
101
  isPreload: false,
102
102
  chains,
103
- config: ctx.config,
103
+ config,
104
104
  isResolved: false,
105
105
  }
106
106
  await handler(
107
107
  Ecosystem.makeOnBlockArgs(
108
108
  ~blockNumber,
109
- ~ecosystem=ctx.config.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}) => switch eventConfig.handler {
124
+ | Event({eventConfig}) =>
125
+ switch eventConfig.handler {
125
126
  | Some(handler) =>
126
127
  await item->runEventHandlerOrThrow(
127
128
  ~handler,
128
129
  ~checkpointId,
129
- ~inMemoryStore,
130
+ ~indexerState,
130
131
  ~loadManager,
131
- ~persistence=ctx.persistence,
132
+ ~persistence,
132
133
  ~chains,
133
- ~config=ctx.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
- ~inMemoryStore,
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}, event}) =>
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
- inMemoryStore,
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
- inMemoryStore,
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
- ~inMemoryStore,
238
+ ~indexerState,
238
239
  ~loadManager,
239
- ~ctx,
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(item, ~checkpointId, ~inMemoryStore, ~loadManager, ~ctx, ~chains)
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
- ~inMemoryStore: InMemoryStore.t,
286
+ ~indexerState: IndexerState.t,
277
287
  ~loadManager,
278
- ~ctx: Ctx.t,
279
- ~chainFetchers: ChainMap.t<ChainFetcher.t>,
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 = chainFetchers->computeChainsState
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 inMemoryStore->InMemoryStore.awaitCapacity
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(~inMemoryStore, ~loadManager, ~ctx, ~chains)
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
- inMemoryStore->InMemoryStore.commitBatch(~batch)
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(~msg=message, ~logger=item->Logging.getItemLogger)
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
  }
@@ -3,26 +3,27 @@
3
3
  import * as Utils from "./Utils.res.mjs";
4
4
  import * as Hrtime from "./bindings/Hrtime.res.mjs";
5
5
  import * as Logging from "./Logging.res.mjs";
6
- import * as ChainMap from "./ChainMap.res.mjs";
6
+ import * as Writing from "./Writing.res.mjs";
7
7
  import * as Ecosystem from "./Ecosystem.res.mjs";
8
+ import * as ChainState from "./ChainState.res.mjs";
8
9
  import * as Prometheus from "./Prometheus.res.mjs";
9
10
  import * as Persistence from "./Persistence.res.mjs";
10
11
  import * as UserContext from "./UserContext.res.mjs";
11
- import * as ChainFetcher from "./ChainFetcher.res.mjs";
12
12
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
13
- import * as InMemoryStore from "./InMemoryStore.res.mjs";
14
13
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
15
14
 
16
- function allChainsEventsProcessedToEndblock(chainFetchers) {
17
- return ChainMap.values(chainFetchers).every(ChainFetcher.hasProcessedToEndblock);
15
+ function allChainsEventsProcessedToEndblock(chainStates) {
16
+ return Object.values(chainStates).every(ChainState.hasProcessedToEndblock);
18
17
  }
19
18
 
20
- function computeChainsState(chainFetchers) {
19
+ function computeChainsState(chainStates) {
21
20
  let chains = {};
22
- let isRealtime = ChainMap.values(chainFetchers).every(ChainFetcher.isReady);
23
- ChainMap.keys(chainFetchers).forEach(chain => {
24
- chains[chain.toString()] = {
25
- id: chain,
21
+ let values = Object.values(chainStates);
22
+ let isRealtime = values.every(ChainState.isReady);
23
+ values.forEach(cs => {
24
+ let chainId = ChainState.chainConfig(cs).id;
25
+ chains[chainId.toString()] = {
26
+ id: chainId,
26
27
  isRealtime: isRealtime
27
28
  };
28
29
  });
@@ -31,13 +32,13 @@ function computeChainsState(chainFetchers) {
31
32
 
32
33
  let ProcessingError = /* @__PURE__ */Primitive_exceptions.create("EventProcessing.ProcessingError");
33
34
 
34
- async function runEventHandlerOrThrow(item, checkpointId, handler, inMemoryStore, loadManager, persistence, chains, config) {
35
+ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config) {
35
36
  let timeBeforeHandler = Hrtime.makeTimer();
36
37
  try {
37
38
  let contextParams = {
38
39
  item: item,
39
40
  checkpointId: checkpointId,
40
- inMemoryStore: inMemoryStore,
41
+ indexerState: indexerState,
41
42
  loadManager: loadManager,
42
43
  persistence: persistence,
43
44
  isPreload: false,
@@ -46,7 +47,7 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, inMemoryStore
46
47
  isResolved: false
47
48
  };
48
49
  await handler({
49
- event: item.event,
50
+ event: Ecosystem.getItemEvent(item, config.ecosystem),
50
51
  context: UserContext.getHandlerContext(contextParams)
51
52
  });
52
53
  contextParams.isResolved = true;
@@ -64,11 +65,11 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, inMemoryStore
64
65
  return Prometheus.ProcessingHandler.increment(item.eventConfig.contractName, item.eventConfig.name, handlerDuration);
65
66
  }
66
67
 
67
- async function runHandlerOrThrow(item, checkpointId, inMemoryStore, loadManager, ctx, chains) {
68
+ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager, persistence, config, chains) {
68
69
  if (item.kind === 0) {
69
70
  let handler = item.eventConfig.handler;
70
71
  if (handler !== undefined) {
71
- return await runEventHandlerOrThrow(item, checkpointId, handler, inMemoryStore, loadManager, ctx.persistence, chains, ctx.config);
72
+ return await runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config);
72
73
  } else {
73
74
  return;
74
75
  }
@@ -77,15 +78,15 @@ async function runHandlerOrThrow(item, checkpointId, inMemoryStore, loadManager,
77
78
  let contextParams = {
78
79
  item: item,
79
80
  checkpointId: checkpointId,
80
- inMemoryStore: inMemoryStore,
81
+ indexerState: indexerState,
81
82
  loadManager: loadManager,
82
- persistence: ctx.persistence,
83
+ persistence: persistence,
83
84
  isPreload: false,
84
85
  chains: chains,
85
- config: ctx.config,
86
+ config: config,
86
87
  isResolved: false
87
88
  };
88
- await item.onBlockConfig.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, ctx.config.ecosystem, UserContext.getHandlerContext(contextParams)));
89
+ await item.onBlockConfig.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
89
90
  contextParams.isResolved = true;
90
91
  return;
91
92
  } catch (raw_exn) {
@@ -100,7 +101,7 @@ async function runHandlerOrThrow(item, checkpointId, inMemoryStore, loadManager,
100
101
  }
101
102
  }
102
103
 
103
- async function preloadBatchOrThrow(batch, loadManager, persistence, config, inMemoryStore, chains) {
104
+ async function preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains) {
104
105
  let promises = [];
105
106
  let itemIdx = 0;
106
107
  for (let checkpointIdx = 0, checkpointIdx_finish = batch.checkpointIds.length; checkpointIdx < checkpointIdx_finish; ++checkpointIdx) {
@@ -117,11 +118,11 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inMe
117
118
  try {
118
119
  let timerRef = Prometheus.PreloadHandler.startOperation(contractName, eventName);
119
120
  promises.push(Utils.$$Promise.silentCatch(handler({
120
- event: item.event,
121
+ event: Ecosystem.getItemEvent(item, config.ecosystem),
121
122
  context: UserContext.getHandlerContext({
122
123
  item: item,
123
124
  checkpointId: checkpointId,
124
- inMemoryStore: inMemoryStore,
125
+ indexerState: indexerState,
125
126
  loadManager: loadManager,
126
127
  persistence: persistence,
127
128
  isPreload: true,
@@ -139,7 +140,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inMe
139
140
  promises.push(Utils.$$Promise.silentCatch(item.onBlockConfig.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext({
140
141
  item: item,
141
142
  checkpointId: checkpointId,
142
- inMemoryStore: inMemoryStore,
143
+ indexerState: indexerState,
143
144
  loadManager: loadManager,
144
145
  persistence: persistence,
145
146
  isPreload: true,
@@ -157,14 +158,14 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inMe
157
158
  await Promise.all(promises);
158
159
  }
159
160
 
160
- async function runBatchHandlersOrThrow(batch, inMemoryStore, loadManager, ctx, chains) {
161
+ async function runBatchHandlersOrThrow(batch, indexerState, loadManager, persistence, config, chains) {
161
162
  let itemIdx = 0;
162
163
  for (let checkpointIdx = 0, checkpointIdx_finish = batch.checkpointIds.length; checkpointIdx < checkpointIdx_finish; ++checkpointIdx) {
163
164
  let checkpointId = batch.checkpointIds[checkpointIdx];
164
165
  let checkpointEventsProcessed = batch.checkpointEventsProcessed[checkpointIdx];
165
166
  for (let idx = 0; idx < checkpointEventsProcessed; ++idx) {
166
167
  let item = batch.items[itemIdx + idx | 0];
167
- await runHandlerOrThrow(item, checkpointId, inMemoryStore, loadManager, ctx, chains);
168
+ await runHandlerOrThrow(item, checkpointId, indexerState, loadManager, persistence, config, chains);
168
169
  }
169
170
  itemIdx = itemIdx + checkpointEventsProcessed | 0;
170
171
  }
@@ -179,9 +180,9 @@ function registerProcessEventBatchMetrics(logger, loadDuration, handlerDuration)
179
180
  Prometheus.ProcessingBatch.registerMetrics(loadDuration, handlerDuration);
180
181
  }
181
182
 
182
- async function processEventBatch(batch, inMemoryStore, loadManager, ctx, chainFetchers) {
183
+ async function processEventBatch(batch, indexerState, loadManager, persistence, config, chainStates) {
183
184
  let totalBatchSize = batch.totalBatchSize;
184
- let chains = computeChainsState(chainFetchers);
185
+ let chains = computeChainsState(chainStates);
185
186
  let logger = Logging.getLogger();
186
187
  Logging.childTrace(logger, {
187
188
  msg: "Started processing batch",
@@ -192,17 +193,17 @@ async function processEventBatch(batch, inMemoryStore, loadManager, ctx, chainFe
192
193
  }))
193
194
  });
194
195
  try {
195
- await InMemoryStore.awaitCapacity(inMemoryStore);
196
+ await Writing.awaitCapacity(indexerState);
196
197
  let timeRef = Hrtime.makeTimer();
197
198
  if (Utils.$$Array.notEmpty(batch.items)) {
198
- await preloadBatchOrThrow(batch, loadManager, ctx.persistence, ctx.config, inMemoryStore, chains);
199
+ await preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains);
199
200
  }
200
201
  let elapsedTimeAfterLoaders = Hrtime.toSecondsFloat(Hrtime.timeSince(timeRef));
201
202
  if (Utils.$$Array.notEmpty(batch.items)) {
202
- await runBatchHandlersOrThrow(batch, inMemoryStore, loadManager, ctx, chains);
203
+ await runBatchHandlersOrThrow(batch, indexerState, loadManager, persistence, config, chains);
203
204
  }
204
205
  let elapsedTimeAfterProcessing = Hrtime.toSecondsFloat(Hrtime.timeSince(timeRef));
205
- InMemoryStore.commitBatch(inMemoryStore, batch);
206
+ Writing.commitBatch(indexerState, batch);
206
207
  let handlerDuration = elapsedTimeAfterProcessing - elapsedTimeAfterLoaders;
207
208
  registerProcessEventBatchMetrics(logger, elapsedTimeAfterLoaders, handlerDuration);
208
209
  return {
@@ -219,7 +220,7 @@ async function processEventBatch(batch, inMemoryStore, loadManager, ctx, chainFe
219
220
  } else if (exn.RE_EXN_ID === ProcessingError) {
220
221
  return {
221
222
  TAG: "Error",
222
- _0: ErrorHandling.make(exn.exn, Logging.getItemLogger(exn.item), exn.message)
223
+ _0: ErrorHandling.make(exn.exn, Ecosystem.getItemLogger(exn.item, config.ecosystem), exn.message)
223
224
  };
224
225
  } else {
225
226
  return {
@@ -1,7 +1,3 @@
1
- let isEarlierUnordered = (item1: (int, int, int), item2: (int, int, int)) => {
2
- item1 < item2
3
- }
4
-
5
1
  // type eventIndex = {
6
2
  // blockNumber: int,
7
3
  // logIndex: int,