envio 3.12.1 → 3.13.0-rc.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 -8
- package/src/BatchProcessing.res +15 -14
- package/src/BatchProcessing.res.mjs +8 -15
- package/src/Bin.res +24 -17
- package/src/Bin.res.mjs +5 -0
- package/src/ChainFetching.res +18 -24
- package/src/ChainFetching.res.mjs +14 -15
- package/src/ChainState.res +103 -38
- package/src/ChainState.res.mjs +79 -22
- package/src/ChainState.resi +14 -2
- package/src/Config.res +32 -0
- package/src/Config.res.mjs +24 -0
- package/src/Core.res +4 -0
- package/src/Core.res.mjs +4 -0
- package/src/CrossChainState.res +109 -11
- package/src/CrossChainState.res.mjs +71 -7
- package/src/CrossChainState.resi +11 -1
- package/src/Env.res +4 -0
- package/src/ErrorHandling.res +15 -4
- package/src/ErrorHandling.res.mjs +16 -5
- package/src/FinalizeBackfill.res +10 -4
- package/src/FinalizeBackfill.res.mjs +5 -3
- package/src/HandlerRegister.res +0 -37
- package/src/HandlerRegister.res.mjs +0 -18
- package/src/IndexerLoop.res +2 -0
- package/src/IndexerLoop.res.mjs +1 -0
- package/src/IndexerState.res +43 -1
- package/src/IndexerState.res.mjs +48 -4
- package/src/IndexerState.resi +11 -0
- package/src/Main.res +128 -268
- package/src/Main.res.mjs +27 -153
- package/src/Metrics.res +268 -102
- package/src/Metrics.res.mjs +227 -48
- package/src/Persistence.res +30 -2
- package/src/Persistence.res.mjs +12 -3
- package/src/PgStorage.res +19 -11
- package/src/PgStorage.res.mjs +13 -10
- package/src/Rollback.res +3 -3
- package/src/Server.res +178 -0
- package/src/Server.res.mjs +143 -0
- package/src/SimulateItems.res +1 -1
- package/src/SimulateItems.res.mjs +1 -1
- package/src/Supervisor.res +542 -0
- package/src/Supervisor.res.mjs +455 -0
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +2 -2
- package/src/Worker.res +101 -0
- package/src/Worker.res.mjs +81 -0
- package/src/bindings/NodeJs.res +50 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/db/InternalTable.res +8 -1
- package/src/db/InternalTable.res.mjs +5 -1
- package/src/sources/AddressSet.res +5 -3
- package/src/sources/AddressStore.res +19 -11
- package/src/sources/AddressStore.res.mjs +2 -7
- package/src/sources/BlockStore.res +10 -9
- package/src/sources/BlockStore.res.mjs +4 -4
- package/src/sources/ChainSources.res +4 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -0
- package/src/sources/EvmChain.res.mjs +3 -1
- package/src/sources/EvmEventItem.res +56 -0
- package/src/sources/EvmEventItem.res.mjs +32 -0
- package/src/sources/EvmHyperSyncSource.res +7 -37
- package/src/sources/EvmHyperSyncSource.res.mjs +8 -29
- package/src/sources/EvmRpcClient.res +41 -59
- package/src/sources/EvmRpcClient.res.mjs +4 -54
- package/src/sources/EvmRpcWs.res +4 -1
- package/src/sources/EvmRpcWs.res.mjs +6 -2
- package/src/sources/FuelHyperSyncSource.res +6 -4
- package/src/sources/FuelHyperSyncSource.res.mjs +7 -9
- package/src/sources/HeightFeed.res +7 -1
- package/src/sources/HeightFeed.res.mjs +9 -7
- package/src/sources/HyperSyncClient.res +1 -14
- package/src/sources/RequestStat.res +7 -0
- package/src/sources/RequestStat.res.mjs +14 -1
- package/src/sources/RpcSource.res +100 -1043
- package/src/sources/RpcSource.res.mjs +81 -1056
- package/src/sources/SimulateSource.res +2 -5
- package/src/sources/SimulateSource.res.mjs +2 -3
- package/src/sources/Source.res +34 -12
- package/src/sources/Source.res.mjs +11 -0
- package/src/sources/SourceManager.res +111 -31
- package/src/sources/SourceManager.res.mjs +65 -31
- package/src/sources/SourceManager.resi +4 -0
- package/src/sources/StartBlockResolver.res +8 -5
- package/src/sources/StartBlockResolver.res.mjs +4 -2
- package/src/sources/SvmHyperSyncSource.res +4 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +4 -6
- package/src/sources/TransactionStore.res +9 -6
- package/src/sources/TransactionStore.res.mjs +2 -2
- package/src/tui/Tui.res +10 -0
- package/src/tui/Tui.res.mjs +15 -0
- package/src/tui/components/SyncETA.res +12 -6
- package/src/tui/components/SyncETA.res.mjs +12 -8
- package/src/LazyLoader.res +0 -135
- package/src/LazyLoader.res.mjs +0 -118
- package/src/bindings/SDSL.res +0 -12
- package/src/bindings/SDSL.res.mjs +0 -9
- package/src/bindings/Yargs.res +0 -8
- package/src/bindings/Yargs.res.mjs +0 -2
- package/src/sources/Rpc.res +0 -185
- package/src/sources/Rpc.res.mjs +0 -183
package/src/ChainState.res
CHANGED
|
@@ -43,6 +43,10 @@ type t = {
|
|
|
43
43
|
maxReorgDepth: int,
|
|
44
44
|
// One-way: past it, everything the chain writes can still be rolled back.
|
|
45
45
|
mutable isInReorgThreshold: bool,
|
|
46
|
+
// How this chain spells the addresses materialised out of its stores, from
|
|
47
|
+
// `lowercaseAddresses`. The stores hold raw bytes; the spelling is decided
|
|
48
|
+
// where they are read.
|
|
49
|
+
shouldChecksum: bool,
|
|
46
50
|
// Holds this chain's transactions (kept in Rust) keyed by (blockNumber,
|
|
47
51
|
// transactionIndex). Fetch responses merge their page in; entries are pruned
|
|
48
52
|
// as the chain progresses and dropped above the target on rollback.
|
|
@@ -58,6 +62,10 @@ type t = {
|
|
|
58
62
|
mutable blockRangeFetchCount: float,
|
|
59
63
|
mutable blockRangeFetchedEvents: float,
|
|
60
64
|
mutable blockRangeFetchedBlocks: float,
|
|
65
|
+
// Whether this chain has said where it finished indexing. Being finished
|
|
66
|
+
// stays true for the rest of the run, and every pass over the chains would
|
|
67
|
+
// say so again.
|
|
68
|
+
mutable reportedFinished: bool,
|
|
61
69
|
mutable reorgCount: int,
|
|
62
70
|
mutable reorgDetectedBlock: option<int>,
|
|
63
71
|
mutable rollbackTargetBlock: option<int>,
|
|
@@ -136,9 +144,10 @@ let make = (
|
|
|
136
144
|
~numEventsProcessed=0.,
|
|
137
145
|
~timestampCaughtUpToHeadOrEndblock=None,
|
|
138
146
|
~isProgressAtHead=false,
|
|
139
|
-
~transactionStore=TransactionStore.make(~ecosystem=Ecosystem.Evm
|
|
147
|
+
~transactionStore=TransactionStore.make(~ecosystem=Ecosystem.Evm),
|
|
140
148
|
~chainDensity=None,
|
|
141
|
-
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm
|
|
149
|
+
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm),
|
|
150
|
+
~shouldChecksum=false,
|
|
142
151
|
~reorgThresholdReadyTolerance=100,
|
|
143
152
|
~perChainEntities: array<Internal.entityConfig>=[],
|
|
144
153
|
~logger: Pino.t,
|
|
@@ -165,12 +174,14 @@ let make = (
|
|
|
165
174
|
isInReorgThreshold,
|
|
166
175
|
transactionStore,
|
|
167
176
|
blockStore,
|
|
177
|
+
shouldChecksum,
|
|
168
178
|
reorgThresholdReadyTolerance,
|
|
169
179
|
blockRangeFetchSeconds: 0.,
|
|
170
180
|
blockRangeParseSeconds: 0.,
|
|
171
181
|
blockRangeFetchCount: 0.,
|
|
172
182
|
blockRangeFetchedEvents: 0.,
|
|
173
183
|
blockRangeFetchedBlocks: 0.,
|
|
184
|
+
reportedFinished: false,
|
|
174
185
|
reorgCount: 0,
|
|
175
186
|
reorgDetectedBlock: None,
|
|
176
187
|
rollbackTargetBlock: None,
|
|
@@ -228,7 +239,6 @@ let makeInternal = (
|
|
|
228
239
|
// chain's addresses into it, and every source client holds the same handle.
|
|
229
240
|
let addressStore = AddressStore.make(
|
|
230
241
|
~ecosystem=config.ecosystem.name,
|
|
231
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
232
242
|
~contracts=AddressStore.contractsOf(~onEventRegistrations, ~contractMapping),
|
|
233
243
|
)
|
|
234
244
|
|
|
@@ -273,17 +283,18 @@ let makeInternal = (
|
|
|
273
283
|
}
|
|
274
284
|
})
|
|
275
285
|
|
|
286
|
+
// Before the sources, which are constructed holding them.
|
|
287
|
+
let blockStore = BlockStore.make(~ecosystem=config.ecosystem.name)
|
|
288
|
+
let transactionStore = TransactionStore.make(~ecosystem=config.ecosystem.name)
|
|
289
|
+
|
|
276
290
|
// Create sources lazily here - this is where API token validation happens
|
|
277
291
|
let sources = ChainSources.make(
|
|
278
292
|
~chainConfig,
|
|
279
293
|
~onEventRegistrations,
|
|
280
294
|
~addressStore,
|
|
281
295
|
~lowercaseAddresses,
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
let blockStore = BlockStore.make(
|
|
285
|
-
~ecosystem=config.ecosystem.name,
|
|
286
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
296
|
+
~blockStore,
|
|
297
|
+
~transactionStore,
|
|
287
298
|
)
|
|
288
299
|
|
|
289
300
|
// Seed the stored reorg checkpoints (hash-only rows) so detection resumes
|
|
@@ -295,7 +306,6 @@ let makeInternal = (
|
|
|
295
306
|
blockHash: cp.blockHash,
|
|
296
307
|
}),
|
|
297
308
|
~ecosystem=config.ecosystem.name,
|
|
298
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
299
309
|
)
|
|
300
310
|
blockStore
|
|
301
311
|
->BlockStore.merge(seedPage, ~fromBlock=0, ~reportOnly=false)
|
|
@@ -329,12 +339,10 @@ let makeInternal = (
|
|
|
329
339
|
~perChainEntities=config.userEntities->EntityTables.perChain,
|
|
330
340
|
~timestampCaughtUpToHeadOrEndblock,
|
|
331
341
|
~numEventsProcessed,
|
|
332
|
-
~transactionStore
|
|
333
|
-
~ecosystem=config.ecosystem.name,
|
|
334
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
335
|
-
),
|
|
342
|
+
~transactionStore,
|
|
336
343
|
~chainDensity,
|
|
337
344
|
~blockStore,
|
|
345
|
+
~shouldChecksum=!lowercaseAddresses,
|
|
338
346
|
~reorgThresholdReadyTolerance=config.reorgThresholdReadyTolerance,
|
|
339
347
|
~logger,
|
|
340
348
|
)
|
|
@@ -394,6 +402,8 @@ let makeFromDbState = (
|
|
|
394
402
|
|
|
395
403
|
let logger = (cs: t) => cs.logger
|
|
396
404
|
let blockStore = (cs: t) => cs.blockStore
|
|
405
|
+
let transactionStore = (cs: t) => cs.transactionStore
|
|
406
|
+
let shouldChecksum = (cs: t) => cs.shouldChecksum
|
|
397
407
|
let entities = (cs: t) => cs.entities
|
|
398
408
|
|
|
399
409
|
// Rollback discards every uncommitted change, so this chain's partition is
|
|
@@ -450,7 +460,7 @@ let setRollbackTargetBlock = (cs: t, ~blockNumber) => cs.rollbackTargetBlock = S
|
|
|
450
460
|
// rather than reaching into it.
|
|
451
461
|
let knownHeight = (cs: t) => cs.fetchState.knownHeight
|
|
452
462
|
let contractAddresses = (cs: t, ~contractName) =>
|
|
453
|
-
cs.addressStore->AddressStore.contractAddresses(contractName)
|
|
463
|
+
cs.addressStore->AddressStore.contractAddresses(contractName, ~shouldChecksum=cs.shouldChecksum)
|
|
454
464
|
|
|
455
465
|
// Hands over the dynamically registered addresses the database hasn't seen yet,
|
|
456
466
|
// up to the block the caller is about to commit, each paired with the checkpoint
|
|
@@ -650,6 +660,30 @@ let hasProcessedToEndblock = (cs: t) => {
|
|
|
650
660
|
}
|
|
651
661
|
}
|
|
652
662
|
|
|
663
|
+
// Where this chain has finished indexing, the first time it gets there.
|
|
664
|
+
// `EndBlock` is terminal: the chain indexed everything it was configured to.
|
|
665
|
+
// `Backfill` is the rest of the history, up to the point where blocks can
|
|
666
|
+
// still be reorged, which is as far as a chain indexes before the indexer
|
|
667
|
+
// crosses into them.
|
|
668
|
+
type finished = EndBlock(int) | Backfill(int)
|
|
669
|
+
|
|
670
|
+
let takeFinished = (cs: t) =>
|
|
671
|
+
if cs.reportedFinished {
|
|
672
|
+
None
|
|
673
|
+
} else {
|
|
674
|
+
switch (cs.fetchState.endBlock, cs->hasProcessedToEndblock, cs.isProgressAtHead) {
|
|
675
|
+
| (Some(endBlock), true, _) => {
|
|
676
|
+
cs.reportedFinished = true
|
|
677
|
+
Some(EndBlock(endBlock))
|
|
678
|
+
}
|
|
679
|
+
| (_, _, true) => {
|
|
680
|
+
cs.reportedFinished = true
|
|
681
|
+
Some(Backfill(cs.committedProgressBlockNumber))
|
|
682
|
+
}
|
|
683
|
+
| _ => None
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
653
687
|
// Caught up as judged by persisted values alone: progress reached the endBlock,
|
|
654
688
|
// or the head the previous run had already observed (less the lag that holds the
|
|
655
689
|
// tip back). Unlike `isFetchingAtHead` this doesn't move when a fresh height
|
|
@@ -730,7 +764,7 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
730
764
|
let {blockNumber} = eventItem
|
|
731
765
|
|
|
732
766
|
switch eventItem.payload->Internal.getPayloadTransaction->Nullable.toOption {
|
|
733
|
-
| Some(_) => () //
|
|
767
|
+
| Some(_) => () // Fuel and Simulate carry the transaction inline.
|
|
734
768
|
| None =>
|
|
735
769
|
let {transactionIndex} = eventItem
|
|
736
770
|
let mask = eventItem.onEventRegistration.fieldSelection.transactionMask
|
|
@@ -757,7 +791,7 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
757
791
|
}
|
|
758
792
|
|
|
759
793
|
switch eventItem.payload->Internal.getPayloadBlock->Nullable.toOption {
|
|
760
|
-
| Some(_) => () //
|
|
794
|
+
| Some(_) => () // Simulate carries the block inline.
|
|
761
795
|
| None =>
|
|
762
796
|
let mask = eventItem.onEventRegistration.fieldSelection.blockMask
|
|
763
797
|
let last = blockItemGroups->Array.length - 1
|
|
@@ -796,13 +830,18 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
796
830
|
// `groupBatchItems`). Store-backed items always get a transaction object - the
|
|
797
831
|
// selected fields, or `{}` when nothing was selected - so `event.transaction`
|
|
798
832
|
// is never `undefined` (matching the inline sources).
|
|
799
|
-
let applyTransactionGroups = async (
|
|
833
|
+
let applyTransactionGroups = async (
|
|
834
|
+
store: TransactionStore.t,
|
|
835
|
+
g: transactionGroups,
|
|
836
|
+
~shouldChecksum,
|
|
837
|
+
) => {
|
|
800
838
|
if g.payloadGroups->Utils.Array.notEmpty {
|
|
801
839
|
if g.anyTransactionFieldSelected {
|
|
802
840
|
let txs = await store->TransactionStore.materialize(
|
|
803
841
|
~blockNumbers=g.txBlockNumbers,
|
|
804
842
|
~transactionIndices=g.transactionIndices,
|
|
805
843
|
~masks=g.transactionMasks,
|
|
844
|
+
~shouldChecksum,
|
|
806
845
|
)
|
|
807
846
|
g.payloadGroups->Array.forEachWithIndex((payloads, i) => {
|
|
808
847
|
let tx = txs->Array.getUnsafe(i)
|
|
@@ -823,11 +862,12 @@ let applyTransactionGroups = async (store: TransactionStore.t, g: transactionGro
|
|
|
823
862
|
}
|
|
824
863
|
|
|
825
864
|
// Materialise a `BlockStore` against precomputed groups (see `groupBatchItems`).
|
|
826
|
-
let applyBlockGroups = async (store: BlockStore.t, g: blockGroups) => {
|
|
865
|
+
let applyBlockGroups = async (store: BlockStore.t, g: blockGroups, ~shouldChecksum) => {
|
|
827
866
|
if g.blockItemGroups->Utils.Array.notEmpty {
|
|
828
867
|
let blocks = await store->BlockStore.materialize(
|
|
829
868
|
~blockNumbers=g.blockBlockNumbers,
|
|
830
869
|
~masks=g.blockMasks,
|
|
870
|
+
~shouldChecksum,
|
|
831
871
|
)
|
|
832
872
|
g.blockItemGroups->Array.forEachWithIndex((group, i) => {
|
|
833
873
|
let block = blocks->Array.getUnsafe(i)
|
|
@@ -843,27 +883,26 @@ let applyBlockGroups = async (store: BlockStore.t, g: blockGroups) => {
|
|
|
843
883
|
let materializeBatchItems = async (cs: t, ~items: array<Internal.item>) => {
|
|
844
884
|
let (txGroups, blockGroups) = items->groupBatchItems
|
|
845
885
|
let _ = await Promise.all2((
|
|
846
|
-
cs.transactionStore->applyTransactionGroups(txGroups),
|
|
847
|
-
cs.blockStore->applyBlockGroups(blockGroups),
|
|
886
|
+
cs.transactionStore->applyTransactionGroups(txGroups, ~shouldChecksum=cs.shouldChecksum),
|
|
887
|
+
cs.blockStore->applyBlockGroups(blockGroups, ~shouldChecksum=cs.shouldChecksum),
|
|
848
888
|
))
|
|
849
889
|
}
|
|
850
890
|
|
|
851
891
|
// Materialise a fetch-response's transactions and blocks onto its items before
|
|
852
|
-
// contract-register handlers read them.
|
|
853
|
-
//
|
|
854
|
-
//
|
|
892
|
+
// contract-register handlers read them. Both come from the chain stores, which
|
|
893
|
+
// the response's pages were merged into once the reorg guard passed: a source
|
|
894
|
+
// that consults those stores to decide what to fetch leaves out what they
|
|
895
|
+
// already hold, so its page alone does not cover its own items.
|
|
855
896
|
let materializePageItems = async (
|
|
856
897
|
~items: array<Internal.item>,
|
|
857
|
-
~transactionStore:
|
|
898
|
+
~transactionStore: TransactionStore.t,
|
|
858
899
|
~blockStore: BlockStore.t,
|
|
900
|
+
~shouldChecksum: bool,
|
|
859
901
|
) => {
|
|
860
902
|
let (txGroups, blockGroups) = items->groupBatchItems
|
|
861
903
|
let _ = await Promise.all2((
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
| None => Promise.resolve()
|
|
865
|
-
},
|
|
866
|
-
blockStore->applyBlockGroups(blockGroups),
|
|
904
|
+
transactionStore->applyTransactionGroups(txGroups, ~shouldChecksum),
|
|
905
|
+
blockStore->applyBlockGroups(blockGroups, ~shouldChecksum),
|
|
867
906
|
))
|
|
868
907
|
}
|
|
869
908
|
|
|
@@ -874,16 +913,7 @@ let handleQueryResult = (
|
|
|
874
913
|
~newRegistrations,
|
|
875
914
|
~latestFetchedBlock: int,
|
|
876
915
|
~knownHeight,
|
|
877
|
-
~transactionStore as txPage: option<TransactionStore.t>,
|
|
878
916
|
) => {
|
|
879
|
-
// Merge this response's transaction page into the chain store in lockstep
|
|
880
|
-
// with appending its items to the buffer. Inline sources contribute no page;
|
|
881
|
-
// the block page was already merged by `registerReorgGuard`.
|
|
882
|
-
switch txPage {
|
|
883
|
-
| Some(page) => cs.transactionStore->TransactionStore.merge(page)
|
|
884
|
-
| None => ()
|
|
885
|
-
}
|
|
886
|
-
|
|
887
917
|
let fs = switch newRegistrations {
|
|
888
918
|
| [] => cs.fetchState
|
|
889
919
|
| _ =>
|
|
@@ -964,6 +994,34 @@ let isInReorgThreshold = (cs: t) => cs.isInReorgThreshold
|
|
|
964
994
|
// progress has run.
|
|
965
995
|
let shouldSaveHistory = (cs: t) =>
|
|
966
996
|
cs.shouldRollbackOnReorg && cs.maxReorgDepth > 0 && cs.isInReorgThreshold
|
|
997
|
+
// What crossing into the recent blocks changed for this chain. Until now it
|
|
998
|
+
// stopped short of the head by its reorg depth, because it kept nothing it
|
|
999
|
+
// could roll back with; crossing lifts both at once. The second half is the
|
|
1000
|
+
// answer to why the indexer starts writing more than it was.
|
|
1001
|
+
// Whether crossing gives this chain anything more to index: the last block it
|
|
1002
|
+
// may fetch afterwards against the last it may fetch now. Read before the
|
|
1003
|
+
// crossing, while the lag being lifted is still the one in place.
|
|
1004
|
+
//
|
|
1005
|
+
// False wherever the lag was never holding this chain back, which is every
|
|
1006
|
+
// configuration that also keeps no history: a chain that isn't rolled back on a
|
|
1007
|
+
// reorg, or has no reorg depth, already fetches as far as it ever will. It is
|
|
1008
|
+
// false too for a chain whose end block sits below the blocks being opened up,
|
|
1009
|
+
// which will never reach one of them.
|
|
1010
|
+
let reorgThresholdLiftsCeiling = (cs: t) => {
|
|
1011
|
+
let ceiling = (~blockLag) => {
|
|
1012
|
+
let head = Pervasives.max(0, cs.fetchState.knownHeight - blockLag)
|
|
1013
|
+
switch cs.fetchState.endBlock {
|
|
1014
|
+
| Some(endBlock) => Pervasives.min(endBlock, head)
|
|
1015
|
+
| None => head
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
ceiling(~blockLag=cs.chainConfig.blockLag) > ceiling(~blockLag=cs.fetchState.blockLag)
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Only ever said by a chain the crossing lifts, and lifting it takes a reorg
|
|
1022
|
+
// depth to have been held back by, which is the same thing that makes the
|
|
1023
|
+
// history below worth keeping. So there is no second form without it.
|
|
1024
|
+
let reorgThresholdEntryMessage = "Indexing the latest blocks now. These can be reorged, so the indexer starts storing a history of every change to roll back with."
|
|
967
1025
|
|
|
968
1026
|
// Snapshot the chain's metadata fields for staging into the chains table.
|
|
969
1027
|
let toChainMetadata = (cs: t): InternalTable.Chains.metaFields => {
|
|
@@ -1051,6 +1109,12 @@ let toChainBeforeBatch = (cs: t, ~isRealtime): Batch.chainBeforeBatch => {
|
|
|
1051
1109
|
|
|
1052
1110
|
// Whether the chain's post-batch fetch frontier is ready to cross into the reorg
|
|
1053
1111
|
// threshold, using the batch's progressed frontier when this chain advanced.
|
|
1112
|
+
// The same question asked of where the chain stands now rather than of where a
|
|
1113
|
+
// batch would leave it. Entering the threshold is what lifts the pre-threshold
|
|
1114
|
+
// lag, so a chain waiting to enter it has fetched as far as it can.
|
|
1115
|
+
let isReadyToEnterReorgThreshold = (cs: t) =>
|
|
1116
|
+
cs.fetchState->FetchState.isReadyToEnterReorgThreshold(~tolerance=cs.reorgThresholdReadyTolerance)
|
|
1117
|
+
|
|
1054
1118
|
let isReadyToEnterReorgThresholdAfterBatch = (cs: t, ~batch: Batch.t) => {
|
|
1055
1119
|
let fetchState = switch batch.progressedChainsById->ChainId.Dict.dangerouslyGetNonOption(
|
|
1056
1120
|
cs.fetchState.chainId,
|
|
@@ -1199,6 +1263,7 @@ let markReady = (cs: t, ~readyAt) =>
|
|
|
1199
1263
|
let rollbackCommittedProgress = (cs: t, blockNumber) =>
|
|
1200
1264
|
if blockNumber !== cs.committedProgressBlockNumber {
|
|
1201
1265
|
cs.committedProgressBlockNumber = blockNumber
|
|
1266
|
+
|
|
1202
1267
|
// Exact block only: the rolled-back region is about to be refetched, and
|
|
1203
1268
|
// the next batch re-establishes the time either way.
|
|
1204
1269
|
cs.committedProgressBlockTime =
|
package/src/ChainState.res.mjs
CHANGED
|
@@ -55,7 +55,7 @@ function validateOnEventRegistrations(chainId, registrations) {
|
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager, committedProgressBlockNumber, committedProgressBlockTimeOpt, safeCheckpointTrackingOpt, shouldRollbackOnReorg, maxReorgDepth, isInReorgThresholdOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, reorgThresholdReadyToleranceOpt, perChainEntitiesOpt, logger) {
|
|
58
|
+
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager, committedProgressBlockNumber, committedProgressBlockTimeOpt, safeCheckpointTrackingOpt, shouldRollbackOnReorg, maxReorgDepth, isInReorgThresholdOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, shouldChecksumOpt, reorgThresholdReadyToleranceOpt, perChainEntitiesOpt, logger) {
|
|
59
59
|
let onEventRegistrations = onEventRegistrationsOpt !== undefined ? onEventRegistrationsOpt : [];
|
|
60
60
|
let committedProgressBlockTime = committedProgressBlockTimeOpt !== undefined ? Primitive_option.valFromOption(committedProgressBlockTimeOpt) : undefined;
|
|
61
61
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
@@ -63,9 +63,10 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
63
63
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
64
64
|
let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
|
|
65
65
|
let isProgressAtHead = isProgressAtHeadOpt !== undefined ? isProgressAtHeadOpt : false;
|
|
66
|
-
let transactionStore = transactionStoreOpt !== undefined ? Primitive_option.valFromOption(transactionStoreOpt) : TransactionStore.make("evm"
|
|
66
|
+
let transactionStore = transactionStoreOpt !== undefined ? Primitive_option.valFromOption(transactionStoreOpt) : TransactionStore.make("evm");
|
|
67
67
|
let chainDensity = chainDensityOpt !== undefined ? Primitive_option.valFromOption(chainDensityOpt) : undefined;
|
|
68
|
-
let blockStore = blockStoreOpt !== undefined ? Primitive_option.valFromOption(blockStoreOpt) : BlockStore.make("evm"
|
|
68
|
+
let blockStore = blockStoreOpt !== undefined ? Primitive_option.valFromOption(blockStoreOpt) : BlockStore.make("evm");
|
|
69
|
+
let shouldChecksum = shouldChecksumOpt !== undefined ? shouldChecksumOpt : false;
|
|
69
70
|
let reorgThresholdReadyTolerance = reorgThresholdReadyToleranceOpt !== undefined ? reorgThresholdReadyToleranceOpt : 100;
|
|
70
71
|
let perChainEntities = perChainEntitiesOpt !== undefined ? perChainEntitiesOpt : [];
|
|
71
72
|
validateOnEventRegistrations(chainConfig.id, onEventRegistrations);
|
|
@@ -88,6 +89,7 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
88
89
|
shouldRollbackOnReorg: shouldRollbackOnReorg,
|
|
89
90
|
maxReorgDepth: maxReorgDepth,
|
|
90
91
|
isInReorgThreshold: isInReorgThreshold,
|
|
92
|
+
shouldChecksum: shouldChecksum,
|
|
91
93
|
transactionStore: transactionStore,
|
|
92
94
|
blockStore: blockStore,
|
|
93
95
|
reorgThresholdReadyTolerance: reorgThresholdReadyTolerance,
|
|
@@ -96,6 +98,7 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
96
98
|
blockRangeFetchCount: 0,
|
|
97
99
|
blockRangeFetchedEvents: 0,
|
|
98
100
|
blockRangeFetchedBlocks: 0,
|
|
101
|
+
reportedFinished: false,
|
|
99
102
|
reorgCount: 0,
|
|
100
103
|
reorgDetectedBlock: undefined,
|
|
101
104
|
rollbackTargetBlock: undefined,
|
|
@@ -136,7 +139,7 @@ function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInR
|
|
|
136
139
|
}
|
|
137
140
|
});
|
|
138
141
|
let lowercaseAddresses = config.lowercaseAddresses;
|
|
139
|
-
let addressStore = AddressStore.make(config.ecosystem.name,
|
|
142
|
+
let addressStore = AddressStore.make(config.ecosystem.name, AddressStore.contractsOf(onEventRegistrations, contractMapping));
|
|
140
143
|
let match$1 = config.ecosystem.name;
|
|
141
144
|
let tmp;
|
|
142
145
|
switch (match$1) {
|
|
@@ -154,18 +157,19 @@ function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInR
|
|
|
154
157
|
return reorgCheckpoint;
|
|
155
158
|
}
|
|
156
159
|
});
|
|
157
|
-
let
|
|
158
|
-
let
|
|
160
|
+
let blockStore = BlockStore.make(config.ecosystem.name);
|
|
161
|
+
let transactionStore = TransactionStore.make(config.ecosystem.name);
|
|
162
|
+
let sources = ChainSources.make(chainConfig, onEventRegistrations, addressStore, lowercaseAddresses, blockStore, transactionStore);
|
|
159
163
|
if (Utils.$$Array.notEmpty(chainReorgCheckpoints)) {
|
|
160
164
|
let seedPage = BlockStore.fromJs(chainReorgCheckpoints.map(cp => ({
|
|
161
165
|
blockNumber: cp.block_number,
|
|
162
166
|
blockHash: cp.block_hash
|
|
163
|
-
})), config.ecosystem.name
|
|
167
|
+
})), config.ecosystem.name);
|
|
164
168
|
blockStore.merge(seedPage, 0, false);
|
|
165
169
|
}
|
|
166
170
|
let firstEventBlock$1 = fetchState.firstEventBlock;
|
|
167
171
|
let chainDensity = firstEventBlock$1 !== undefined && progressBlockNumber > firstEventBlock$1 && numEventsProcessed > 0 ? numEventsProcessed / (progressBlockNumber - firstEventBlock$1 | 0) : undefined;
|
|
168
|
-
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), progressBlockNumber, Primitive_option.some(committedProgressBlockTime), Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), config.shouldRollbackOnReorg, maxReorgDepth, isInReorgThreshold, numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(
|
|
172
|
+
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), progressBlockNumber, Primitive_option.some(committedProgressBlockTime), Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), config.shouldRollbackOnReorg, maxReorgDepth, isInReorgThreshold, numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(transactionStore), Primitive_option.some(chainDensity), Primitive_option.some(blockStore), !lowercaseAddresses, config.reorgThresholdReadyTolerance, EntityTables.perChain(config.userEntities), logger);
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
function logger(cs) {
|
|
@@ -176,6 +180,14 @@ function blockStore(cs) {
|
|
|
176
180
|
return cs.blockStore;
|
|
177
181
|
}
|
|
178
182
|
|
|
183
|
+
function transactionStore(cs) {
|
|
184
|
+
return cs.transactionStore;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function shouldChecksum(cs) {
|
|
188
|
+
return cs.shouldChecksum;
|
|
189
|
+
}
|
|
190
|
+
|
|
179
191
|
function entities(cs) {
|
|
180
192
|
return cs.entities;
|
|
181
193
|
}
|
|
@@ -254,7 +266,7 @@ function knownHeight(cs) {
|
|
|
254
266
|
}
|
|
255
267
|
|
|
256
268
|
function contractAddresses(cs, contractName) {
|
|
257
|
-
return cs.addressStore.contractAddresses(contractName);
|
|
269
|
+
return cs.addressStore.contractAddresses(contractName, cs.shouldChecksum);
|
|
258
270
|
}
|
|
259
271
|
|
|
260
272
|
function drainAddressesForWrite(cs, toBlockInclusive, checkpointBlockNumbers) {
|
|
@@ -409,6 +421,29 @@ function hasProcessedToEndblock(cs) {
|
|
|
409
421
|
}
|
|
410
422
|
}
|
|
411
423
|
|
|
424
|
+
function takeFinished(cs) {
|
|
425
|
+
if (cs.reportedFinished) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
let match = cs.fetchState.endBlock;
|
|
429
|
+
let match$1 = hasProcessedToEndblock(cs);
|
|
430
|
+
let match$2 = cs.isProgressAtHead;
|
|
431
|
+
if (match !== undefined && match$1) {
|
|
432
|
+
cs.reportedFinished = true;
|
|
433
|
+
return {
|
|
434
|
+
TAG: "EndBlock",
|
|
435
|
+
_0: match
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
if (match$2) {
|
|
439
|
+
cs.reportedFinished = true;
|
|
440
|
+
return {
|
|
441
|
+
TAG: "Backfill",
|
|
442
|
+
_0: cs.committedProgressBlockNumber
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
412
447
|
function isDurablyCaughtUp(cs) {
|
|
413
448
|
let fetchState = cs.fetchState;
|
|
414
449
|
let committedProgressBlockNumber = cs.committedProgressBlockNumber;
|
|
@@ -511,12 +546,12 @@ function groupBatchItems(items) {
|
|
|
511
546
|
];
|
|
512
547
|
}
|
|
513
548
|
|
|
514
|
-
async function applyTransactionGroups(store, g) {
|
|
549
|
+
async function applyTransactionGroups(store, g, shouldChecksum) {
|
|
515
550
|
if (!Utils.$$Array.notEmpty(g.payloadGroups)) {
|
|
516
551
|
return;
|
|
517
552
|
}
|
|
518
553
|
if (g.anyTransactionFieldSelected) {
|
|
519
|
-
let txs = await store.materialize(g.txBlockNumbers, g.transactionIndices, g.transactionMasks);
|
|
554
|
+
let txs = await store.materialize(g.txBlockNumbers, g.transactionIndices, g.transactionMasks, shouldChecksum);
|
|
520
555
|
g.payloadGroups.forEach((payloads, i) => {
|
|
521
556
|
let tx = txs[i];
|
|
522
557
|
payloads.forEach(payload => {
|
|
@@ -537,11 +572,11 @@ async function applyTransactionGroups(store, g) {
|
|
|
537
572
|
});
|
|
538
573
|
}
|
|
539
574
|
|
|
540
|
-
async function applyBlockGroups(store, g) {
|
|
575
|
+
async function applyBlockGroups(store, g, shouldChecksum) {
|
|
541
576
|
if (!Utils.$$Array.notEmpty(g.blockItemGroups)) {
|
|
542
577
|
return;
|
|
543
578
|
}
|
|
544
|
-
let blocks = await store.materialize(g.blockBlockNumbers, g.blockMasks);
|
|
579
|
+
let blocks = await store.materialize(g.blockBlockNumbers, g.blockMasks, shouldChecksum);
|
|
545
580
|
g.blockItemGroups.forEach((group, i) => {
|
|
546
581
|
let block = blocks[i];
|
|
547
582
|
group.forEach(ei => {
|
|
@@ -553,23 +588,20 @@ async function applyBlockGroups(store, g) {
|
|
|
553
588
|
async function materializeBatchItems(cs, items) {
|
|
554
589
|
let match = groupBatchItems(items);
|
|
555
590
|
await Promise.all([
|
|
556
|
-
applyTransactionGroups(cs.transactionStore, match[0]),
|
|
557
|
-
applyBlockGroups(cs.blockStore, match[1])
|
|
591
|
+
applyTransactionGroups(cs.transactionStore, match[0], cs.shouldChecksum),
|
|
592
|
+
applyBlockGroups(cs.blockStore, match[1], cs.shouldChecksum)
|
|
558
593
|
]);
|
|
559
594
|
}
|
|
560
595
|
|
|
561
|
-
async function materializePageItems(items, transactionStore, blockStore) {
|
|
596
|
+
async function materializePageItems(items, transactionStore, blockStore, shouldChecksum) {
|
|
562
597
|
let match = groupBatchItems(items);
|
|
563
598
|
await Promise.all([
|
|
564
|
-
|
|
565
|
-
applyBlockGroups(blockStore, match[1])
|
|
599
|
+
applyTransactionGroups(transactionStore, match[0], shouldChecksum),
|
|
600
|
+
applyBlockGroups(blockStore, match[1], shouldChecksum)
|
|
566
601
|
]);
|
|
567
602
|
}
|
|
568
603
|
|
|
569
|
-
function handleQueryResult(cs, query, newItems, newRegistrations, latestFetchedBlock, knownHeight
|
|
570
|
-
if (txPage !== undefined) {
|
|
571
|
-
cs.transactionStore.merge(Primitive_option.valFromOption(txPage));
|
|
572
|
-
}
|
|
604
|
+
function handleQueryResult(cs, query, newItems, newRegistrations, latestFetchedBlock, knownHeight) {
|
|
573
605
|
let fs = newRegistrations.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.addressStore, Primitive_int.max(knownHeight, latestFetchedBlock), newRegistrations) : cs.fetchState;
|
|
574
606
|
cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), knownHeight);
|
|
575
607
|
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.itemsEst);
|
|
@@ -666,6 +698,19 @@ function shouldSaveHistory(cs) {
|
|
|
666
698
|
}
|
|
667
699
|
}
|
|
668
700
|
|
|
701
|
+
function reorgThresholdLiftsCeiling(cs) {
|
|
702
|
+
let ceiling = blockLag => {
|
|
703
|
+
let head = Primitive_int.max(0, cs.fetchState.knownHeight - blockLag | 0);
|
|
704
|
+
let endBlock = cs.fetchState.endBlock;
|
|
705
|
+
if (endBlock !== undefined) {
|
|
706
|
+
return Primitive_int.min(endBlock, head);
|
|
707
|
+
} else {
|
|
708
|
+
return head;
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
return ceiling(cs.chainConfig.blockLag) > ceiling(cs.fetchState.blockLag);
|
|
712
|
+
}
|
|
713
|
+
|
|
669
714
|
function toChainMetadata(cs) {
|
|
670
715
|
return {
|
|
671
716
|
first_event_block: Stdlib_Null.fromOption(cs.fetchState.firstEventBlock),
|
|
@@ -741,6 +786,10 @@ function toChainBeforeBatch(cs, isRealtime) {
|
|
|
741
786
|
};
|
|
742
787
|
}
|
|
743
788
|
|
|
789
|
+
function isReadyToEnterReorgThreshold(cs) {
|
|
790
|
+
return FetchState.isReadyToEnterReorgThreshold(cs.reorgThresholdReadyTolerance, cs.fetchState);
|
|
791
|
+
}
|
|
792
|
+
|
|
744
793
|
function isReadyToEnterReorgThresholdAfterBatch(cs, batch) {
|
|
745
794
|
let chainAfterBatch = batch.progressedChainsById[cs.fetchState.chainId];
|
|
746
795
|
let fetchState = chainAfterBatch !== undefined ? chainAfterBatch.fetchState : cs.fetchState;
|
|
@@ -878,6 +927,8 @@ function rollback(cs, rolledBackTo) {
|
|
|
878
927
|
return rolledBackAddresses$1;
|
|
879
928
|
}
|
|
880
929
|
|
|
930
|
+
let reorgThresholdEntryMessage = "Indexing the latest blocks now. These can be reorged, so the indexer starts storing a history of every change to roll back with.";
|
|
931
|
+
|
|
881
932
|
export {
|
|
882
933
|
configStorageRows,
|
|
883
934
|
seedConfigAddresses,
|
|
@@ -885,6 +936,8 @@ export {
|
|
|
885
936
|
makeFromDbState,
|
|
886
937
|
logger,
|
|
887
938
|
blockStore,
|
|
939
|
+
transactionStore,
|
|
940
|
+
shouldChecksum,
|
|
888
941
|
entities,
|
|
889
942
|
resetEntities,
|
|
890
943
|
sourceManager,
|
|
@@ -921,7 +974,11 @@ export {
|
|
|
921
974
|
toMetrics,
|
|
922
975
|
toChainMetadata,
|
|
923
976
|
toChainBeforeBatch,
|
|
977
|
+
isReadyToEnterReorgThreshold,
|
|
924
978
|
isReadyToEnterReorgThresholdAfterBatch,
|
|
979
|
+
takeFinished,
|
|
980
|
+
reorgThresholdLiftsCeiling,
|
|
981
|
+
reorgThresholdEntryMessage,
|
|
925
982
|
hasProcessedToEndblock,
|
|
926
983
|
isDurablyCaughtUp,
|
|
927
984
|
getHighestBlockBelowThreshold,
|
package/src/ChainState.resi
CHANGED
|
@@ -34,6 +34,7 @@ let make: (
|
|
|
34
34
|
~transactionStore: TransactionStore.t=?,
|
|
35
35
|
~chainDensity: option<float>=?,
|
|
36
36
|
~blockStore: BlockStore.t=?,
|
|
37
|
+
~shouldChecksum: bool=?,
|
|
37
38
|
~reorgThresholdReadyTolerance: int=?,
|
|
38
39
|
~perChainEntities: array<Internal.entityConfig>=?,
|
|
39
40
|
~logger: Pino.t,
|
|
@@ -54,6 +55,8 @@ let makeFromDbState: (
|
|
|
54
55
|
// Accessors.
|
|
55
56
|
let logger: t => Pino.t
|
|
56
57
|
let blockStore: t => BlockStore.t
|
|
58
|
+
let transactionStore: t => TransactionStore.t
|
|
59
|
+
let shouldChecksum: t => bool
|
|
57
60
|
let entities: t => EntityTables.t
|
|
58
61
|
let resetEntities: (t, ~perChainEntities: array<Internal.entityConfig>) => unit
|
|
59
62
|
let sourceManager: t => SourceManager.t
|
|
@@ -120,9 +123,14 @@ let dispatch: (
|
|
|
120
123
|
let toMetrics: t => Metrics.chainMetrics
|
|
121
124
|
let toChainMetadata: t => InternalTable.Chains.metaFields
|
|
122
125
|
let toChainBeforeBatch: (t, ~isRealtime: bool) => Batch.chainBeforeBatch
|
|
126
|
+
let isReadyToEnterReorgThreshold: t => bool
|
|
123
127
|
let isReadyToEnterReorgThresholdAfterBatch: (t, ~batch: Batch.t) => bool
|
|
124
128
|
|
|
125
129
|
// Derived (pure).
|
|
130
|
+
type finished = EndBlock(int) | Backfill(int)
|
|
131
|
+
let takeFinished: t => option<finished>
|
|
132
|
+
let reorgThresholdLiftsCeiling: t => bool
|
|
133
|
+
let reorgThresholdEntryMessage: string
|
|
126
134
|
let hasProcessedToEndblock: t => bool
|
|
127
135
|
let isDurablyCaughtUp: t => bool
|
|
128
136
|
let getHighestBlockBelowThreshold: t => int
|
|
@@ -139,14 +147,18 @@ let handleQueryResult: (
|
|
|
139
147
|
~newRegistrations: array<AddressStore.registration>,
|
|
140
148
|
~latestFetchedBlock: int,
|
|
141
149
|
~knownHeight: int,
|
|
142
|
-
~transactionStore: option<TransactionStore.t>,
|
|
143
150
|
) => unit
|
|
144
151
|
let materializeBatchItems: (t, ~items: array<Internal.item>) => promise<unit>
|
|
145
152
|
let materializePageItems: (
|
|
146
153
|
~items: array<Internal.item>,
|
|
147
|
-
~transactionStore:
|
|
154
|
+
~transactionStore: TransactionStore.t,
|
|
148
155
|
~blockStore: BlockStore.t,
|
|
156
|
+
~shouldChecksum: bool,
|
|
149
157
|
) => promise<unit>
|
|
158
|
+
// Merges the page's blocks into the chain's store as it checks them: the check
|
|
159
|
+
// is the merge's own conflict report, so a page that passes is already applied.
|
|
160
|
+
// Its transactions are a separate page, merged by the caller once this returns
|
|
161
|
+
// no reorg.
|
|
150
162
|
let registerReorgGuard: (
|
|
151
163
|
t,
|
|
152
164
|
~blockStore: BlockStore.t,
|
package/src/Config.res
CHANGED
|
@@ -625,6 +625,16 @@ let getChain = (config, ~chainId) =>
|
|
|
625
625
|
"No chain with id " ++ chainId->ChainId.toString ++ " found in config.yaml",
|
|
626
626
|
)
|
|
627
627
|
|
|
628
|
+
// Whether every entity belongs to exactly one chain. Read off the checkpoint
|
|
629
|
+
// sequence rather than the entities again: a chain gets a counter of its own
|
|
630
|
+
// only when no other chain can reach its rows, which is the same fact and the
|
|
631
|
+
// one that makes splitting a run across processes safe.
|
|
632
|
+
let isPerChain = (config: t) =>
|
|
633
|
+
switch config.checkpointSequence {
|
|
634
|
+
| PerChain => true
|
|
635
|
+
| SharedAcrossChains => false
|
|
636
|
+
}
|
|
637
|
+
|
|
628
638
|
// Narrows a config to the chains one `envio start --chain` process drives.
|
|
629
639
|
// `contractMapping` is deliberately left whole: its ids are what the migration
|
|
630
640
|
// that created the schema stored, and one rebuilt from a subset would hand the
|
|
@@ -1221,6 +1231,24 @@ let prime = (json: JSON.t): unit => {
|
|
|
1221
1231
|
cached := None
|
|
1222
1232
|
}
|
|
1223
1233
|
|
|
1234
|
+
// What the command decided rather than the project's files: which chains this
|
|
1235
|
+
// process drives, and whether the run is a dev run. A worker parses the same
|
|
1236
|
+
// files its supervisor did, so these are the only two it cannot arrive at on
|
|
1237
|
+
// its own.
|
|
1238
|
+
let withCommandFields = (json: JSON.t, ~chainIds, ~isDev) =>
|
|
1239
|
+
switch json->JSON.Decode.object {
|
|
1240
|
+
| Some(fields) => {
|
|
1241
|
+
let narrowed = fields->Dict.copy
|
|
1242
|
+
narrowed->Dict.set(
|
|
1243
|
+
"isolatedChains",
|
|
1244
|
+
chainIds->S.reverseConvertToJsonOrThrow(S.array(ChainId.schema)),
|
|
1245
|
+
)
|
|
1246
|
+
narrowed->Dict.set("isDev", JSON.Encode.bool(isDev))
|
|
1247
|
+
JSON.Object(narrowed)
|
|
1248
|
+
}
|
|
1249
|
+
| None => JsError.throwWithMessage("Invalid indexer config: not an object")
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1224
1252
|
let getPublicConfigJson = () =>
|
|
1225
1253
|
switch primedJson.contents {
|
|
1226
1254
|
| Some(json) => json
|
|
@@ -1266,6 +1294,10 @@ let stripSensitiveData = (json: JSON.t): JSON.t => {
|
|
|
1266
1294
|
cloned
|
|
1267
1295
|
}
|
|
1268
1296
|
|
|
1297
|
+
// What the storage layer records as the config this schema was built from,
|
|
1298
|
+
// and checks a resuming run against.
|
|
1299
|
+
let envioInfo = () => getPublicConfigJson()->stripSensitiveData
|
|
1300
|
+
|
|
1269
1301
|
// Postgres jsonb doesn't preserve key order, so canonicalize with sorted
|
|
1270
1302
|
// keys before string-comparing.
|
|
1271
1303
|
let rec canonicalJson = (json: JSON.t): JSON.t =>
|