envio 3.3.0-alpha.1 → 3.3.0-alpha.10

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 (136) hide show
  1. package/evm.schema.json +10 -0
  2. package/index.d.ts +45 -25
  3. package/package.json +7 -7
  4. package/src/Address.res +5 -2
  5. package/src/Address.res.mjs +3 -1
  6. package/src/Api.res +1 -1
  7. package/src/Api.res.mjs +1 -1
  8. package/src/Batch.res +0 -6
  9. package/src/Batch.res.mjs +1 -12
  10. package/src/BatchProcessing.res +7 -12
  11. package/src/BatchProcessing.res.mjs +8 -7
  12. package/src/Bin.res +3 -0
  13. package/src/Bin.res.mjs +4 -0
  14. package/src/ChainFetching.res +43 -9
  15. package/src/ChainFetching.res.mjs +34 -15
  16. package/src/ChainMetadata.res +1 -11
  17. package/src/ChainMetadata.res.mjs +1 -10
  18. package/src/ChainState.res +605 -151
  19. package/src/ChainState.res.mjs +427 -104
  20. package/src/ChainState.resi +72 -4
  21. package/src/Config.res +61 -33
  22. package/src/Config.res.mjs +50 -10
  23. package/src/ContractRegisterContext.res +2 -12
  24. package/src/ContractRegisterContext.res.mjs +3 -5
  25. package/src/Core.res +14 -3
  26. package/src/CrossChainState.res +113 -89
  27. package/src/CrossChainState.res.mjs +64 -60
  28. package/src/CrossChainState.resi +1 -1
  29. package/src/Ecosystem.res +5 -6
  30. package/src/Ecosystem.res.mjs +3 -3
  31. package/src/Envio.res +17 -11
  32. package/src/EnvioGlobal.res +53 -0
  33. package/src/EnvioGlobal.res.mjs +31 -0
  34. package/src/EventConfigBuilder.res +177 -88
  35. package/src/EventConfigBuilder.res.mjs +99 -42
  36. package/src/EventProcessing.res +74 -28
  37. package/src/EventProcessing.res.mjs +55 -29
  38. package/src/ExitOnCaughtUp.res +10 -2
  39. package/src/ExitOnCaughtUp.res.mjs +10 -1
  40. package/src/FetchState.res +544 -356
  41. package/src/FetchState.res.mjs +412 -471
  42. package/src/HandlerLoader.res +8 -104
  43. package/src/HandlerLoader.res.mjs +2 -81
  44. package/src/HandlerRegister.res +518 -144
  45. package/src/HandlerRegister.res.mjs +285 -133
  46. package/src/HandlerRegister.resi +24 -8
  47. package/src/IndexerState.res +10 -3
  48. package/src/IndexerState.res.mjs +11 -4
  49. package/src/IndexerState.resi +2 -1
  50. package/src/IndexingAddresses.res +108 -0
  51. package/src/IndexingAddresses.res.mjs +101 -0
  52. package/src/IndexingAddresses.resi +34 -0
  53. package/src/Internal.res +155 -46
  54. package/src/Internal.res.mjs +30 -2
  55. package/src/LoadLayer.res +5 -5
  56. package/src/LoadLayer.res.mjs +6 -6
  57. package/src/LogSelection.res +102 -165
  58. package/src/LogSelection.res.mjs +101 -116
  59. package/src/Main.res +71 -236
  60. package/src/Main.res.mjs +60 -145
  61. package/src/Metrics.res +74 -0
  62. package/src/Metrics.res.mjs +75 -0
  63. package/src/PgStorage.res +4 -4
  64. package/src/PgStorage.res.mjs +5 -5
  65. package/src/Prometheus.res +10 -63
  66. package/src/Prometheus.res.mjs +124 -171
  67. package/src/PruneStaleHistory.res +2 -2
  68. package/src/PruneStaleHistory.res.mjs +3 -3
  69. package/src/RawEvent.res +7 -2
  70. package/src/RawEvent.res.mjs +4 -4
  71. package/src/Rollback.res +3 -3
  72. package/src/Rollback.res.mjs +4 -4
  73. package/src/RollbackCommit.res +4 -1
  74. package/src/RollbackCommit.res.mjs +3 -2
  75. package/src/SimulateDeadInputTracker.res +85 -0
  76. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  77. package/src/SimulateDeadInputTracker.resi +12 -0
  78. package/src/SimulateItems.res +91 -23
  79. package/src/SimulateItems.res.mjs +55 -32
  80. package/src/TestIndexer.res +54 -40
  81. package/src/TestIndexer.res.mjs +37 -30
  82. package/src/bindings/Performance.res +7 -0
  83. package/src/bindings/Performance.res.mjs +21 -0
  84. package/src/bindings/Performance.resi +7 -0
  85. package/src/bindings/Viem.res +0 -41
  86. package/src/bindings/Viem.res.mjs +1 -43
  87. package/src/sources/BlockStore.res +46 -0
  88. package/src/sources/BlockStore.res.mjs +24 -0
  89. package/src/sources/EventRouter.res +36 -33
  90. package/src/sources/EventRouter.res.mjs +13 -14
  91. package/src/sources/Evm.res +83 -72
  92. package/src/sources/Evm.res.mjs +53 -69
  93. package/src/sources/EvmChain.res +18 -20
  94. package/src/sources/EvmChain.res.mjs +15 -15
  95. package/src/sources/EvmRpcClient.res +74 -5
  96. package/src/sources/EvmRpcClient.res.mjs +13 -4
  97. package/src/sources/FieldMask.res +39 -0
  98. package/src/sources/FieldMask.res.mjs +42 -0
  99. package/src/sources/Fuel.res +9 -6
  100. package/src/sources/Fuel.res.mjs +5 -10
  101. package/src/sources/HyperFuelSource.res +46 -50
  102. package/src/sources/HyperFuelSource.res.mjs +64 -54
  103. package/src/sources/HyperSync.res +39 -7
  104. package/src/sources/HyperSync.res.mjs +57 -37
  105. package/src/sources/HyperSync.resi +12 -2
  106. package/src/sources/HyperSyncClient.res +22 -111
  107. package/src/sources/HyperSyncClient.res.mjs +2 -30
  108. package/src/sources/HyperSyncHeightStream.res +1 -8
  109. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  110. package/src/sources/HyperSyncSource.res +94 -107
  111. package/src/sources/HyperSyncSource.res.mjs +82 -86
  112. package/src/sources/Rpc.res +15 -47
  113. package/src/sources/Rpc.res.mjs +25 -56
  114. package/src/sources/RpcSource.res +320 -467
  115. package/src/sources/RpcSource.res.mjs +268 -385
  116. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  117. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  118. package/src/sources/SimulateSource.res +10 -4
  119. package/src/sources/SimulateSource.res.mjs +16 -6
  120. package/src/sources/Source.res +34 -6
  121. package/src/sources/SourceManager.res +77 -19
  122. package/src/sources/SourceManager.res.mjs +63 -21
  123. package/src/sources/SourceManager.resi +10 -0
  124. package/src/sources/Svm.res +31 -16
  125. package/src/sources/Svm.res.mjs +36 -13
  126. package/src/sources/SvmHyperSyncClient.res +5 -32
  127. package/src/sources/SvmHyperSyncSource.res +159 -134
  128. package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
  129. package/src/sources/TransactionStore.res +49 -0
  130. package/src/sources/TransactionStore.res.mjs +30 -0
  131. package/src/tui/Tui.res +13 -16
  132. package/src/tui/Tui.res.mjs +12 -14
  133. package/svm.schema.json +49 -37
  134. package/src/bindings/Hrtime.res +0 -58
  135. package/src/bindings/Hrtime.res.mjs +0 -90
  136. package/src/bindings/Hrtime.resi +0 -30
@@ -39,7 +39,7 @@ let runEventHandlerOrThrow = async (
39
39
  let eventItem = item->Internal.castUnsafeEventItem
40
40
 
41
41
  //Include the load in time before handler
42
- let timeBeforeHandler = Hrtime.makeTimer()
42
+ let timeBeforeHandler = Performance.now()
43
43
 
44
44
  try {
45
45
  let contextParams: UserContext.contextParams = {
@@ -72,10 +72,10 @@ let runEventHandlerOrThrow = async (
72
72
  }),
73
73
  )
74
74
  }
75
- let handlerDuration = timeBeforeHandler->Hrtime.timeSince->Hrtime.toSecondsFloat
75
+ let handlerDuration = timeBeforeHandler->Performance.secondsSince
76
76
  Prometheus.ProcessingHandler.increment(
77
- ~contract=eventItem.eventConfig.contractName,
78
- ~event=eventItem.eventConfig.name,
77
+ ~contract=eventItem.onEventRegistration.eventConfig.contractName,
78
+ ~event=eventItem.onEventRegistration.eventConfig.name,
79
79
  ~duration=handlerDuration,
80
80
  )
81
81
  }
@@ -90,7 +90,7 @@ let runHandlerOrThrow = async (
90
90
  ~chains: Internal.chains,
91
91
  ) => {
92
92
  switch item {
93
- | Block({onBlockConfig: {handler}, blockNumber}) =>
93
+ | Block({onBlockRegistration: {handler}, blockNumber}) =>
94
94
  try {
95
95
  let contextParams: UserContext.contextParams = {
96
96
  item,
@@ -121,8 +121,8 @@ let runHandlerOrThrow = async (
121
121
  }),
122
122
  )
123
123
  }
124
- | Event({eventConfig}) =>
125
- switch eventConfig.handler {
124
+ | Event({onEventRegistration}) =>
125
+ switch onEventRegistration.handler {
126
126
  | Some(handler) =>
127
127
  await item->runEventHandlerOrThrow(
128
128
  ~handler,
@@ -161,7 +161,7 @@ let preloadBatchOrThrow = async (
161
161
  for idx in 0 to checkpointEventsProcessed - 1 {
162
162
  let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
163
163
  switch item {
164
- | Event({eventConfig: {handler, contractName, name: eventName}}) =>
164
+ | Event({onEventRegistration: {handler, eventConfig: {contractName, name: eventName}}}) =>
165
165
  switch handler {
166
166
  | None => ()
167
167
  | Some(handler) =>
@@ -200,7 +200,7 @@ let preloadBatchOrThrow = async (
200
200
  | _ => ()
201
201
  }
202
202
  }
203
- | Block({onBlockConfig: {handler}, blockNumber}) =>
203
+ | Block({onBlockRegistration: {handler}, blockNumber}) =>
204
204
  try {
205
205
  promises->Array.push(
206
206
  handler({
@@ -264,11 +264,19 @@ let runBatchHandlersOrThrow = async (
264
264
  }
265
265
  }
266
266
 
267
- let registerProcessEventBatchMetrics = (~logger, ~loadDuration, ~handlerDuration) => {
268
- logger->Logging.childTrace({
269
- "msg": "Finished processing batch",
270
- "loader_time_elapsed": loadDuration,
271
- "handlers_time_elapsed": handlerDuration,
267
+ let registerProcessEventBatchMetrics = (
268
+ ~logger,
269
+ ~batch: Batch.t,
270
+ ~loadDuration,
271
+ ~handlerDuration,
272
+ ) => {
273
+ batch.progressedChainsById->Dict.forEachWithKey((chainAfterBatch, chainId) => {
274
+ logger->Logging.childTrace({
275
+ "msg": "Finished processing",
276
+ "chainId": chainId->Int.fromString->Option.getUnsafe,
277
+ "batchSize": chainAfterBatch.batchSize,
278
+ "progress": chainAfterBatch.progressBlockNumber,
279
+ })
272
280
  })
273
281
 
274
282
  Prometheus.ProcessingBatch.registerMetrics(~loadDuration, ~handlerDuration)
@@ -281,6 +289,39 @@ type logPartitionInfo = {
281
289
  lastItemBlockNumber?: int,
282
290
  }
283
291
 
292
+ // Off the hot path: bulk-materialise the selected transaction and block fields
293
+ // for the batch's store-backed (HyperSync) items and write them onto the
294
+ // payloads, so handlers read plain objects. A batch can span chains, each with
295
+ // its own stores and field masks, so group items by chain before materialising.
296
+ let materializeBatchEvents = async (
297
+ batch: Batch.t,
298
+ ~chainStates: dict<ChainState.t>,
299
+ ~ecosystem,
300
+ ) => {
301
+ switch chainStates->Dict.valuesToArray {
302
+ // Single-chain indexers (the common case): every item belongs to the one
303
+ // chain, so skip the per-chain grouping and its allocations.
304
+ | [cs] => await cs->ChainState.materializeBatchItems(~items=batch.items, ~ecosystem)
305
+ | _ =>
306
+ let itemsByChain: dict<array<Internal.item>> = Dict.make()
307
+ batch.items->Array.forEach(item => {
308
+ let chainId = item->Internal.getItemChainId->Int.toString
309
+ switch itemsByChain->Utils.Dict.dangerouslyGetNonOption(chainId) {
310
+ | Some(items) => items->Array.push(item)
311
+ | None => itemsByChain->Dict.set(chainId, [item])
312
+ }
313
+ })
314
+
315
+ let _ = await itemsByChain
316
+ ->Dict.toArray
317
+ ->Array.map(async ((chainId, items)) => {
318
+ let cs = chainStates->Dict.getUnsafe(chainId)
319
+ await cs->ChainState.materializeBatchItems(~items, ~ecosystem)
320
+ })
321
+ ->Promise.all
322
+ }
323
+ }
324
+
284
325
  let processEventBatch = async (
285
326
  ~batch: Batch.t,
286
327
  ~indexerState: IndexerState.t,
@@ -289,33 +330,33 @@ let processEventBatch = async (
289
330
  ~config: Config.t,
290
331
  ~chainStates: dict<ChainState.t>,
291
332
  ) => {
292
- let totalBatchSize = batch.totalBatchSize
293
333
  // Compute chains state for this batch
294
334
  let chains: Internal.chains = chainStates->computeChainsState
295
335
 
296
336
  let logger = Logging.getLogger()
297
- logger->Logging.childTrace({
298
- "msg": "Started processing batch",
299
- "totalBatchSize": totalBatchSize,
300
- "chains": batch.progressedChainsById->Utils.Dict.mapValues(chainAfterBatch => {
301
- {
302
- "batchSize": chainAfterBatch.batchSize,
303
- "progress": chainAfterBatch.progressBlockNumber,
304
- }
305
- }),
337
+
338
+ batch.progressedChainsById->Dict.forEachWithKey((chainAfterBatch, chainId) => {
339
+ logger->Logging.childTrace({
340
+ "msg": "Started processing",
341
+ "chainId": chainId->Int.fromString->Option.getUnsafe,
342
+ "batchSize": chainAfterBatch.batchSize,
343
+ })
306
344
  })
307
345
 
308
346
  try {
309
347
  // Backpressure: keep processing within keepLatestChangesLimit of the cycle.
310
348
  await indexerState->Writing.awaitCapacity
311
349
 
312
- let timeRef = Hrtime.makeTimer()
350
+ let timeRef = Performance.now()
313
351
 
314
352
  if batch.items->Utils.Array.notEmpty {
353
+ // Materialise store-backed transactions onto payloads before any handler
354
+ // (preload or execute) reads them.
355
+ await materializeBatchEvents(batch, ~chainStates, ~ecosystem=config.ecosystem.name)
315
356
  await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
316
357
  }
317
358
 
318
- let elapsedTimeAfterLoaders = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
359
+ let elapsedTimeAfterLoaders = timeRef->Performance.secondsSince
319
360
 
320
361
  if batch.items->Utils.Array.notEmpty {
321
362
  await batch->runBatchHandlersOrThrow(
@@ -327,13 +368,18 @@ let processEventBatch = async (
327
368
  )
328
369
  }
329
370
 
330
- let elapsedTimeAfterProcessing = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
371
+ let elapsedTimeAfterProcessing = timeRef->Performance.secondsSince
331
372
 
332
373
  indexerState->Writing.commitBatch(~batch)
333
374
 
334
375
  let loaderDuration = elapsedTimeAfterLoaders
335
376
  let handlerDuration = elapsedTimeAfterProcessing -. loaderDuration
336
- registerProcessEventBatchMetrics(~logger, ~loadDuration=loaderDuration, ~handlerDuration)
377
+ registerProcessEventBatchMetrics(
378
+ ~logger,
379
+ ~batch,
380
+ ~loadDuration=loaderDuration,
381
+ ~handlerDuration,
382
+ )
337
383
  Ok()
338
384
  } catch {
339
385
  | Persistence.StorageError({message, reason}) =>
@@ -1,13 +1,16 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Utils from "./Utils.res.mjs";
4
- import * as Hrtime from "./bindings/Hrtime.res.mjs";
5
4
  import * as Logging from "./Logging.res.mjs";
6
5
  import * as Writing from "./Writing.res.mjs";
6
+ import * as Internal from "./Internal.res.mjs";
7
7
  import * as Ecosystem from "./Ecosystem.res.mjs";
8
8
  import * as ChainState from "./ChainState.res.mjs";
9
9
  import * as Prometheus from "./Prometheus.res.mjs";
10
+ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
11
+ import * as Performance from "./bindings/Performance.res.mjs";
10
12
  import * as Persistence from "./Persistence.res.mjs";
13
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
11
14
  import * as UserContext from "./UserContext.res.mjs";
12
15
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
13
16
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
@@ -33,7 +36,7 @@ function computeChainsState(chainStates) {
33
36
  let ProcessingError = /* @__PURE__ */Primitive_exceptions.create("EventProcessing.ProcessingError");
34
37
 
35
38
  async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config) {
36
- let timeBeforeHandler = Hrtime.makeTimer();
39
+ let timeBeforeHandler = Performance.now();
37
40
  try {
38
41
  let contextParams = {
39
42
  item: item,
@@ -61,13 +64,13 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState,
61
64
  Error: new Error()
62
65
  };
63
66
  }
64
- let handlerDuration = Hrtime.toSecondsFloat(Hrtime.timeSince(timeBeforeHandler));
65
- return Prometheus.ProcessingHandler.increment(item.eventConfig.contractName, item.eventConfig.name, handlerDuration);
67
+ let handlerDuration = Performance.secondsSince(timeBeforeHandler);
68
+ return Prometheus.ProcessingHandler.increment(item.onEventRegistration.eventConfig.contractName, item.onEventRegistration.eventConfig.name, handlerDuration);
66
69
  }
67
70
 
68
71
  async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager, persistence, config, chains) {
69
72
  if (item.kind === 0) {
70
- let handler = item.eventConfig.handler;
73
+ let handler = item.onEventRegistration.handler;
71
74
  if (handler !== undefined) {
72
75
  return await runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config);
73
76
  } else {
@@ -86,7 +89,7 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
86
89
  config: config,
87
90
  isResolved: false
88
91
  };
89
- await item.onBlockConfig.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
92
+ await item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
90
93
  contextParams.isResolved = true;
91
94
  return;
92
95
  } catch (raw_exn) {
@@ -110,11 +113,12 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
110
113
  for (let idx = 0; idx < checkpointEventsProcessed; ++idx) {
111
114
  let item = batch.items[itemIdx + idx | 0];
112
115
  if (item.kind === 0) {
113
- let match = item.eventConfig;
116
+ let match = item.onEventRegistration;
114
117
  let handler = match.handler;
115
118
  if (handler !== undefined) {
116
- let contractName = match.contractName;
117
- let eventName = match.name;
119
+ let match$1 = match.eventConfig;
120
+ let contractName = match$1.contractName;
121
+ let eventName = match$1.name;
118
122
  try {
119
123
  let timerRef = Prometheus.PreloadHandler.startOperation(contractName, eventName);
120
124
  promises.push(Utils.$$Promise.silentCatch(handler({
@@ -137,7 +141,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
137
141
  }
138
142
  } else {
139
143
  try {
140
- promises.push(Utils.$$Promise.silentCatch(item.onBlockConfig.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext({
144
+ promises.push(Utils.$$Promise.silentCatch(item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext({
141
145
  item: item,
142
146
  checkpointId: checkpointId,
143
147
  indexerState: indexerState,
@@ -171,41 +175,62 @@ async function runBatchHandlersOrThrow(batch, indexerState, loadManager, persist
171
175
  }
172
176
  }
173
177
 
174
- function registerProcessEventBatchMetrics(logger, loadDuration, handlerDuration) {
175
- Logging.childTrace(logger, {
176
- msg: "Finished processing batch",
177
- loader_time_elapsed: loadDuration,
178
- handlers_time_elapsed: handlerDuration
179
- });
178
+ function registerProcessEventBatchMetrics(logger, batch, loadDuration, handlerDuration) {
179
+ Stdlib_Dict.forEachWithKey(batch.progressedChainsById, (chainAfterBatch, chainId) => Logging.childTrace(logger, {
180
+ msg: "Finished processing",
181
+ chainId: Stdlib_Int.fromString(chainId, undefined),
182
+ batchSize: chainAfterBatch.batchSize,
183
+ progress: chainAfterBatch.progressBlockNumber
184
+ }));
180
185
  Prometheus.ProcessingBatch.registerMetrics(loadDuration, handlerDuration);
181
186
  }
182
187
 
188
+ async function materializeBatchEvents(batch, chainStates, ecosystem) {
189
+ let match = Object.values(chainStates);
190
+ if (match.length !== 1) {
191
+ let itemsByChain = {};
192
+ batch.items.forEach(item => {
193
+ let chainId = Internal.getItemChainId(item).toString();
194
+ let items = itemsByChain[chainId];
195
+ if (items !== undefined) {
196
+ items.push(item);
197
+ } else {
198
+ itemsByChain[chainId] = [item];
199
+ }
200
+ });
201
+ await Promise.all(Object.entries(itemsByChain).map(async param => {
202
+ let cs = chainStates[param[0]];
203
+ return await ChainState.materializeBatchItems(cs, param[1], ecosystem);
204
+ }));
205
+ return;
206
+ }
207
+ let cs = match[0];
208
+ return await ChainState.materializeBatchItems(cs, batch.items, ecosystem);
209
+ }
210
+
183
211
  async function processEventBatch(batch, indexerState, loadManager, persistence, config, chainStates) {
184
- let totalBatchSize = batch.totalBatchSize;
185
212
  let chains = computeChainsState(chainStates);
186
213
  let logger = Logging.getLogger();
187
- Logging.childTrace(logger, {
188
- msg: "Started processing batch",
189
- totalBatchSize: totalBatchSize,
190
- chains: Utils.Dict.mapValues(batch.progressedChainsById, chainAfterBatch => ({
191
- batchSize: chainAfterBatch.batchSize,
192
- progress: chainAfterBatch.progressBlockNumber
193
- }))
194
- });
214
+ Stdlib_Dict.forEachWithKey(batch.progressedChainsById, (chainAfterBatch, chainId) => Logging.childTrace(logger, {
215
+ msg: "Started processing",
216
+ chainId: Stdlib_Int.fromString(chainId, undefined),
217
+ batchSize: chainAfterBatch.batchSize
218
+ }));
195
219
  try {
196
220
  await Writing.awaitCapacity(indexerState);
197
- let timeRef = Hrtime.makeTimer();
221
+ let timeRef = Performance.now();
198
222
  if (Utils.$$Array.notEmpty(batch.items)) {
223
+ await materializeBatchEvents(batch, chainStates, config.ecosystem.name);
199
224
  await preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains);
200
225
  }
201
- let elapsedTimeAfterLoaders = Hrtime.toSecondsFloat(Hrtime.timeSince(timeRef));
226
+ let elapsedTimeAfterLoaders = Performance.secondsSince(timeRef);
202
227
  if (Utils.$$Array.notEmpty(batch.items)) {
203
228
  await runBatchHandlersOrThrow(batch, indexerState, loadManager, persistence, config, chains);
204
229
  }
205
- let elapsedTimeAfterProcessing = Hrtime.toSecondsFloat(Hrtime.timeSince(timeRef));
230
+ let elapsedTimeAfterProcessing = Performance.secondsSince(timeRef);
206
231
  Writing.commitBatch(indexerState, batch);
207
232
  let handlerDuration = elapsedTimeAfterProcessing - elapsedTimeAfterLoaders;
208
- registerProcessEventBatchMetrics(logger, elapsedTimeAfterLoaders, handlerDuration);
233
+ registerProcessEventBatchMetrics(logger, batch, elapsedTimeAfterLoaders, handlerDuration);
209
234
  return {
210
235
  TAG: "Ok",
211
236
  _0: undefined
@@ -240,6 +265,7 @@ export {
240
265
  preloadBatchOrThrow,
241
266
  runBatchHandlersOrThrow,
242
267
  registerProcessEventBatchMetrics,
268
+ materializeBatchEvents,
243
269
  processEventBatch,
244
270
  }
245
271
  /* Utils Not a pure module */
@@ -4,7 +4,15 @@ let run = async (state: IndexerState.t) => {
4
4
  ChainMetadata.stage(state)
5
5
  await state->Writing.flush
6
6
  if !(state->IndexerState.isStopped) && !(state->IndexerState.isResolvingReorg) {
7
- Logging.info("Exiting with success")
8
- NodeJs.process->NodeJs.exitWithCode(Success)
7
+ // A simulate run fails here when a provided item never reached a handler —
8
+ // dead test code. The tracker is None (a no-op) off the simulate path.
9
+ switch state
10
+ ->IndexerState.simulateDeadInputTracker
11
+ ->Option.flatMap(SimulateDeadInputTracker.failureMessage) {
12
+ | None =>
13
+ Logging.info("Exiting with success")
14
+ NodeJs.process->NodeJs.exitWithCode(Success)
15
+ | Some(message) => state->IndexerState.errorExit(ErrorHandling.make(Utils.Error.make(message)))
16
+ }
9
17
  }
10
18
  }
@@ -5,11 +5,20 @@ import * as Writing from "./Writing.res.mjs";
5
5
  import * as Process from "process";
6
6
  import * as IndexerState from "./IndexerState.res.mjs";
7
7
  import * as ChainMetadata from "./ChainMetadata.res.mjs";
8
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
9
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
10
+ import * as SimulateDeadInputTracker from "./SimulateDeadInputTracker.res.mjs";
8
11
 
9
12
  async function run(state) {
10
13
  ChainMetadata.stage(state);
11
14
  await Writing.flush(state);
12
- if (!IndexerState.isStopped(state) && !IndexerState.isResolvingReorg(state)) {
15
+ if (IndexerState.isStopped(state) || IndexerState.isResolvingReorg(state)) {
16
+ return;
17
+ }
18
+ let message = Stdlib_Option.flatMap(IndexerState.simulateDeadInputTracker(state), SimulateDeadInputTracker.failureMessage);
19
+ if (message !== undefined) {
20
+ return IndexerState.errorExit(state, ErrorHandling.make(new Error(message), undefined, undefined));
21
+ } else {
13
22
  Logging.info("Exiting with success");
14
23
  Process.exit(0);
15
24
  return;