envio 3.13.0-alpha.0 → 3.13.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 +4 -5
- package/src/BatchProcessing.res.mjs +4 -11
- package/src/ChainFetching.res +18 -38
- package/src/ChainFetching.res.mjs +14 -20
- package/src/ChainState.res +113 -77
- package/src/ChainState.res.mjs +90 -73
- package/src/ChainState.resi +14 -5
- package/src/Config.res +14 -17
- package/src/Config.res.mjs +5 -20
- package/src/CrossChainState.res +68 -20
- package/src/CrossChainState.res.mjs +48 -5
- package/src/CrossChainState.resi +1 -0
- package/src/Env.res +2 -2
- package/src/ErrorHandling.res +15 -4
- package/src/ErrorHandling.res.mjs +16 -5
- package/src/FinalizeBackfill.res +21 -9
- package/src/FinalizeBackfill.res.mjs +17 -4
- package/src/HandlerRegister.res +0 -37
- package/src/HandlerRegister.res.mjs +0 -18
- package/src/IndexerState.res +2 -0
- package/src/IndexerState.res.mjs +5 -0
- package/src/IndexerState.resi +1 -0
- package/src/Logging.res +6 -38
- package/src/Logging.res.mjs +5 -32
- package/src/Main.res +6 -9
- package/src/Main.res.mjs +3 -5
- package/src/Metrics.res +9 -4
- package/src/Metrics.res.mjs +3 -3
- package/src/Persistence.res +6 -3
- package/src/Persistence.res.mjs +5 -3
- package/src/PgStorage.res +2 -2
- package/src/PgStorage.res.mjs +2 -2
- package/src/Rollback.res +3 -3
- package/src/Server.res +0 -3
- package/src/SimulateItems.res +1 -1
- package/src/SimulateItems.res.mjs +1 -1
- package/src/Supervisor.res +236 -109
- package/src/Supervisor.res.mjs +185 -55
- package/src/TestIndexer.res +6 -3
- package/src/TestIndexer.res.mjs +3 -3
- package/src/Worker.res +6 -0
- package/src/Worker.res.mjs +2 -1
- package/src/bindings/NodeJs.res +25 -16
- package/src/bindings/NodeJs.res.mjs +8 -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 +4 -18
- package/src/tui/Tui.res.mjs +3 -6
- 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,9 +62,10 @@ type t = {
|
|
|
58
62
|
mutable blockRangeFetchCount: float,
|
|
59
63
|
mutable blockRangeFetchedEvents: float,
|
|
60
64
|
mutable blockRangeFetchedBlocks: float,
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
|
|
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,
|
|
64
69
|
mutable reorgCount: int,
|
|
65
70
|
mutable reorgDetectedBlock: option<int>,
|
|
66
71
|
mutable rollbackTargetBlock: option<int>,
|
|
@@ -139,9 +144,10 @@ let make = (
|
|
|
139
144
|
~numEventsProcessed=0.,
|
|
140
145
|
~timestampCaughtUpToHeadOrEndblock=None,
|
|
141
146
|
~isProgressAtHead=false,
|
|
142
|
-
~transactionStore=TransactionStore.make(~ecosystem=Ecosystem.Evm
|
|
147
|
+
~transactionStore=TransactionStore.make(~ecosystem=Ecosystem.Evm),
|
|
143
148
|
~chainDensity=None,
|
|
144
|
-
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm
|
|
149
|
+
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm),
|
|
150
|
+
~shouldChecksum=false,
|
|
145
151
|
~reorgThresholdReadyTolerance=100,
|
|
146
152
|
~perChainEntities: array<Internal.entityConfig>=[],
|
|
147
153
|
~logger: Pino.t,
|
|
@@ -168,13 +174,14 @@ let make = (
|
|
|
168
174
|
isInReorgThreshold,
|
|
169
175
|
transactionStore,
|
|
170
176
|
blockStore,
|
|
177
|
+
shouldChecksum,
|
|
171
178
|
reorgThresholdReadyTolerance,
|
|
172
179
|
blockRangeFetchSeconds: 0.,
|
|
173
180
|
blockRangeParseSeconds: 0.,
|
|
174
181
|
blockRangeFetchCount: 0.,
|
|
175
182
|
blockRangeFetchedEvents: 0.,
|
|
176
183
|
blockRangeFetchedBlocks: 0.,
|
|
177
|
-
|
|
184
|
+
reportedFinished: false,
|
|
178
185
|
reorgCount: 0,
|
|
179
186
|
reorgDetectedBlock: None,
|
|
180
187
|
rollbackTargetBlock: None,
|
|
@@ -232,7 +239,6 @@ let makeInternal = (
|
|
|
232
239
|
// chain's addresses into it, and every source client holds the same handle.
|
|
233
240
|
let addressStore = AddressStore.make(
|
|
234
241
|
~ecosystem=config.ecosystem.name,
|
|
235
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
236
242
|
~contracts=AddressStore.contractsOf(~onEventRegistrations, ~contractMapping),
|
|
237
243
|
)
|
|
238
244
|
|
|
@@ -277,17 +283,18 @@ let makeInternal = (
|
|
|
277
283
|
}
|
|
278
284
|
})
|
|
279
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
|
+
|
|
280
290
|
// Create sources lazily here - this is where API token validation happens
|
|
281
291
|
let sources = ChainSources.make(
|
|
282
292
|
~chainConfig,
|
|
283
293
|
~onEventRegistrations,
|
|
284
294
|
~addressStore,
|
|
285
295
|
~lowercaseAddresses,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
let blockStore = BlockStore.make(
|
|
289
|
-
~ecosystem=config.ecosystem.name,
|
|
290
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
296
|
+
~blockStore,
|
|
297
|
+
~transactionStore,
|
|
291
298
|
)
|
|
292
299
|
|
|
293
300
|
// Seed the stored reorg checkpoints (hash-only rows) so detection resumes
|
|
@@ -299,7 +306,6 @@ let makeInternal = (
|
|
|
299
306
|
blockHash: cp.blockHash,
|
|
300
307
|
}),
|
|
301
308
|
~ecosystem=config.ecosystem.name,
|
|
302
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
303
309
|
)
|
|
304
310
|
blockStore
|
|
305
311
|
->BlockStore.merge(seedPage, ~fromBlock=0, ~reportOnly=false)
|
|
@@ -333,12 +339,10 @@ let makeInternal = (
|
|
|
333
339
|
~perChainEntities=config.userEntities->EntityTables.perChain,
|
|
334
340
|
~timestampCaughtUpToHeadOrEndblock,
|
|
335
341
|
~numEventsProcessed,
|
|
336
|
-
~transactionStore
|
|
337
|
-
~ecosystem=config.ecosystem.name,
|
|
338
|
-
~shouldChecksum=!lowercaseAddresses,
|
|
339
|
-
),
|
|
342
|
+
~transactionStore,
|
|
340
343
|
~chainDensity,
|
|
341
344
|
~blockStore,
|
|
345
|
+
~shouldChecksum=!lowercaseAddresses,
|
|
342
346
|
~reorgThresholdReadyTolerance=config.reorgThresholdReadyTolerance,
|
|
343
347
|
~logger,
|
|
344
348
|
)
|
|
@@ -398,6 +402,8 @@ let makeFromDbState = (
|
|
|
398
402
|
|
|
399
403
|
let logger = (cs: t) => cs.logger
|
|
400
404
|
let blockStore = (cs: t) => cs.blockStore
|
|
405
|
+
let transactionStore = (cs: t) => cs.transactionStore
|
|
406
|
+
let shouldChecksum = (cs: t) => cs.shouldChecksum
|
|
401
407
|
let entities = (cs: t) => cs.entities
|
|
402
408
|
|
|
403
409
|
// Rollback discards every uncommitted change, so this chain's partition is
|
|
@@ -420,7 +426,6 @@ let getLatestValidScannedBlock = (cs: t, ~blockStore: BlockStore.t, ~blockNumber
|
|
|
420
426
|
->BlockStore.latestValidBlockFromStore(blockStore, blockNumbers)
|
|
421
427
|
->Null.toOption
|
|
422
428
|
let safeCheckpointTracking = (cs: t) => cs.safeCheckpointTracking
|
|
423
|
-
let isProgressAtHead = (cs: t) => cs.isProgressAtHead
|
|
424
429
|
let committedProgressBlockNumber = (cs: t) => cs.committedProgressBlockNumber
|
|
425
430
|
let committedProgressBlockTime = (cs: t) => cs.committedProgressBlockTime
|
|
426
431
|
let numEventsProcessed = (cs: t) => cs.numEventsProcessed
|
|
@@ -454,7 +459,7 @@ let setRollbackTargetBlock = (cs: t, ~blockNumber) => cs.rollbackTargetBlock = S
|
|
|
454
459
|
// rather than reaching into it.
|
|
455
460
|
let knownHeight = (cs: t) => cs.fetchState.knownHeight
|
|
456
461
|
let contractAddresses = (cs: t, ~contractName) =>
|
|
457
|
-
cs.addressStore->AddressStore.contractAddresses(contractName)
|
|
462
|
+
cs.addressStore->AddressStore.contractAddresses(contractName, ~shouldChecksum=cs.shouldChecksum)
|
|
458
463
|
|
|
459
464
|
// Hands over the dynamically registered addresses the database hasn't seen yet,
|
|
460
465
|
// up to the block the caller is about to commit, each paired with the checkpoint
|
|
@@ -646,37 +651,6 @@ let dispatch = (
|
|
|
646
651
|
|
|
647
652
|
// --- Derived (pure). ---
|
|
648
653
|
|
|
649
|
-
%%private(
|
|
650
|
-
// Where the fetch frontier has just landed. Below the reorg threshold a chain
|
|
651
|
-
// can only fetch the finalized range, so reaching the end of it is not
|
|
652
|
-
// reaching the head — the rest opens up once the indexer enters the threshold.
|
|
653
|
-
let fetchedTo = (cs: t) =>
|
|
654
|
-
switch cs.fetchState.endBlock {
|
|
655
|
-
| Some(endBlock) if endBlock <= cs.fetchState.knownHeight - cs.fetchState.blockLag => (
|
|
656
|
-
"the end block",
|
|
657
|
-
endBlock,
|
|
658
|
-
)
|
|
659
|
-
| _ =>
|
|
660
|
-
cs.isInReorgThreshold
|
|
661
|
-
? ("the chain head", cs.fetchState.knownHeight)
|
|
662
|
-
: ("the safe block", cs.fetchState.knownHeight - cs.fetchState.blockLag)
|
|
663
|
-
}
|
|
664
|
-
)
|
|
665
|
-
|
|
666
|
-
// What this chain has just reached, the first time it reaches it. `None` once
|
|
667
|
-
// it has been reported: a chain catches up to a moving head over and over, and
|
|
668
|
-
// the milestone is the same one every time. A new one — the head past the
|
|
669
|
-
// threshold, an end block — is a line of its own.
|
|
670
|
-
let takeFetchedTo = (cs: t) => {
|
|
671
|
-
let (target, block) = cs->fetchedTo
|
|
672
|
-
if cs.reportedFetchedTo == Some(target) {
|
|
673
|
-
None
|
|
674
|
-
} else {
|
|
675
|
-
cs.reportedFetchedTo = Some(target)
|
|
676
|
-
Some((target, block))
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
654
|
let hasProcessedToEndblock = (cs: t) => {
|
|
681
655
|
let {committedProgressBlockNumber, fetchState} = cs
|
|
682
656
|
switch fetchState.endBlock {
|
|
@@ -709,6 +683,45 @@ let isDurablyCaughtUp = (cs: t) => {
|
|
|
709
683
|
atEndBlock || atHead
|
|
710
684
|
}
|
|
711
685
|
|
|
686
|
+
// This chain has indexed everything there was to index: it reached its end
|
|
687
|
+
// block, or its progress reached the head. The single reading of that, for
|
|
688
|
+
// everything that turns on it — what the chain reports, and whether the whole
|
|
689
|
+
// process may finalize.
|
|
690
|
+
//
|
|
691
|
+
// Both spellings, because neither covers the other: `isProgressAtHead` latches
|
|
692
|
+
// the moment a batch's progress met the head known when it was created, which a
|
|
693
|
+
// head that has since moved on would read as behind; `isDurablyCaughtUp` judges
|
|
694
|
+
// the head as it stands, which is all a run resumed at the head has — it has no
|
|
695
|
+
// batch to latch anything.
|
|
696
|
+
let hasCaughtUp = (cs: t) => cs.isProgressAtHead || cs->isDurablyCaughtUp
|
|
697
|
+
|
|
698
|
+
// Where this chain has finished indexing, the first time it gets there.
|
|
699
|
+
// `EndBlock` is terminal: the chain indexed everything it was configured to.
|
|
700
|
+
// `Backfill` is the rest of the history, up to the point where blocks can
|
|
701
|
+
// still be reorged, which is as far as a chain indexes before the indexer
|
|
702
|
+
// crosses into them.
|
|
703
|
+
type finished = EndBlock(int) | Backfill(int)
|
|
704
|
+
|
|
705
|
+
let takeFinished = (cs: t) =>
|
|
706
|
+
if cs.reportedFinished {
|
|
707
|
+
None
|
|
708
|
+
} else {
|
|
709
|
+
switch (cs.fetchState.endBlock, cs->hasProcessedToEndblock, cs->hasCaughtUp) {
|
|
710
|
+
| (Some(endBlock), true, _) => {
|
|
711
|
+
cs.reportedFinished = true
|
|
712
|
+
Some(EndBlock(endBlock))
|
|
713
|
+
}
|
|
714
|
+
| (_, _, true) => {
|
|
715
|
+
cs.reportedFinished = true
|
|
716
|
+
// Finishing a backfill happens in a run, and a chain resumed with its
|
|
717
|
+
// `ready_at` already committed did none in this one. Being at the end
|
|
718
|
+
// block, above, stays true across runs and is said on every one.
|
|
719
|
+
cs->isReady ? None : Some(Backfill(cs.committedProgressBlockNumber))
|
|
720
|
+
}
|
|
721
|
+
| _ => None
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
712
725
|
let getHighestBlockBelowThreshold = (cs: t): int => {
|
|
713
726
|
let highestBlockBelowThreshold = cs.fetchState.knownHeight - cs.maxReorgDepth
|
|
714
727
|
highestBlockBelowThreshold < 0 ? 0 : highestBlockBelowThreshold
|
|
@@ -765,7 +778,7 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
765
778
|
let {blockNumber} = eventItem
|
|
766
779
|
|
|
767
780
|
switch eventItem.payload->Internal.getPayloadTransaction->Nullable.toOption {
|
|
768
|
-
| Some(_) => () //
|
|
781
|
+
| Some(_) => () // Fuel and Simulate carry the transaction inline.
|
|
769
782
|
| None =>
|
|
770
783
|
let {transactionIndex} = eventItem
|
|
771
784
|
let mask = eventItem.onEventRegistration.fieldSelection.transactionMask
|
|
@@ -792,7 +805,7 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
792
805
|
}
|
|
793
806
|
|
|
794
807
|
switch eventItem.payload->Internal.getPayloadBlock->Nullable.toOption {
|
|
795
|
-
| Some(_) => () //
|
|
808
|
+
| Some(_) => () // Simulate carries the block inline.
|
|
796
809
|
| None =>
|
|
797
810
|
let mask = eventItem.onEventRegistration.fieldSelection.blockMask
|
|
798
811
|
let last = blockItemGroups->Array.length - 1
|
|
@@ -831,13 +844,18 @@ let groupBatchItems = (items: array<Internal.item>): (transactionGroups, blockGr
|
|
|
831
844
|
// `groupBatchItems`). Store-backed items always get a transaction object - the
|
|
832
845
|
// selected fields, or `{}` when nothing was selected - so `event.transaction`
|
|
833
846
|
// is never `undefined` (matching the inline sources).
|
|
834
|
-
let applyTransactionGroups = async (
|
|
847
|
+
let applyTransactionGroups = async (
|
|
848
|
+
store: TransactionStore.t,
|
|
849
|
+
g: transactionGroups,
|
|
850
|
+
~shouldChecksum,
|
|
851
|
+
) => {
|
|
835
852
|
if g.payloadGroups->Utils.Array.notEmpty {
|
|
836
853
|
if g.anyTransactionFieldSelected {
|
|
837
854
|
let txs = await store->TransactionStore.materialize(
|
|
838
855
|
~blockNumbers=g.txBlockNumbers,
|
|
839
856
|
~transactionIndices=g.transactionIndices,
|
|
840
857
|
~masks=g.transactionMasks,
|
|
858
|
+
~shouldChecksum,
|
|
841
859
|
)
|
|
842
860
|
g.payloadGroups->Array.forEachWithIndex((payloads, i) => {
|
|
843
861
|
let tx = txs->Array.getUnsafe(i)
|
|
@@ -858,11 +876,12 @@ let applyTransactionGroups = async (store: TransactionStore.t, g: transactionGro
|
|
|
858
876
|
}
|
|
859
877
|
|
|
860
878
|
// Materialise a `BlockStore` against precomputed groups (see `groupBatchItems`).
|
|
861
|
-
let applyBlockGroups = async (store: BlockStore.t, g: blockGroups) => {
|
|
879
|
+
let applyBlockGroups = async (store: BlockStore.t, g: blockGroups, ~shouldChecksum) => {
|
|
862
880
|
if g.blockItemGroups->Utils.Array.notEmpty {
|
|
863
881
|
let blocks = await store->BlockStore.materialize(
|
|
864
882
|
~blockNumbers=g.blockBlockNumbers,
|
|
865
883
|
~masks=g.blockMasks,
|
|
884
|
+
~shouldChecksum,
|
|
866
885
|
)
|
|
867
886
|
g.blockItemGroups->Array.forEachWithIndex((group, i) => {
|
|
868
887
|
let block = blocks->Array.getUnsafe(i)
|
|
@@ -878,27 +897,26 @@ let applyBlockGroups = async (store: BlockStore.t, g: blockGroups) => {
|
|
|
878
897
|
let materializeBatchItems = async (cs: t, ~items: array<Internal.item>) => {
|
|
879
898
|
let (txGroups, blockGroups) = items->groupBatchItems
|
|
880
899
|
let _ = await Promise.all2((
|
|
881
|
-
cs.transactionStore->applyTransactionGroups(txGroups),
|
|
882
|
-
cs.blockStore->applyBlockGroups(blockGroups),
|
|
900
|
+
cs.transactionStore->applyTransactionGroups(txGroups, ~shouldChecksum=cs.shouldChecksum),
|
|
901
|
+
cs.blockStore->applyBlockGroups(blockGroups, ~shouldChecksum=cs.shouldChecksum),
|
|
883
902
|
))
|
|
884
903
|
}
|
|
885
904
|
|
|
886
905
|
// Materialise a fetch-response's transactions and blocks onto its items before
|
|
887
|
-
// contract-register handlers read them.
|
|
888
|
-
//
|
|
889
|
-
//
|
|
906
|
+
// contract-register handlers read them. Both come from the chain stores, which
|
|
907
|
+
// the response's pages were merged into once the reorg guard passed: a source
|
|
908
|
+
// that consults those stores to decide what to fetch leaves out what they
|
|
909
|
+
// already hold, so its page alone does not cover its own items.
|
|
890
910
|
let materializePageItems = async (
|
|
891
911
|
~items: array<Internal.item>,
|
|
892
|
-
~transactionStore:
|
|
912
|
+
~transactionStore: TransactionStore.t,
|
|
893
913
|
~blockStore: BlockStore.t,
|
|
914
|
+
~shouldChecksum: bool,
|
|
894
915
|
) => {
|
|
895
916
|
let (txGroups, blockGroups) = items->groupBatchItems
|
|
896
917
|
let _ = await Promise.all2((
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
| None => Promise.resolve()
|
|
900
|
-
},
|
|
901
|
-
blockStore->applyBlockGroups(blockGroups),
|
|
918
|
+
transactionStore->applyTransactionGroups(txGroups, ~shouldChecksum),
|
|
919
|
+
blockStore->applyBlockGroups(blockGroups, ~shouldChecksum),
|
|
902
920
|
))
|
|
903
921
|
}
|
|
904
922
|
|
|
@@ -909,16 +927,7 @@ let handleQueryResult = (
|
|
|
909
927
|
~newRegistrations,
|
|
910
928
|
~latestFetchedBlock: int,
|
|
911
929
|
~knownHeight,
|
|
912
|
-
~transactionStore as txPage: option<TransactionStore.t>,
|
|
913
930
|
) => {
|
|
914
|
-
// Merge this response's transaction page into the chain store in lockstep
|
|
915
|
-
// with appending its items to the buffer. Inline sources contribute no page;
|
|
916
|
-
// the block page was already merged by `registerReorgGuard`.
|
|
917
|
-
switch txPage {
|
|
918
|
-
| Some(page) => cs.transactionStore->TransactionStore.merge(page)
|
|
919
|
-
| None => ()
|
|
920
|
-
}
|
|
921
|
-
|
|
922
931
|
let fs = switch newRegistrations {
|
|
923
932
|
| [] => cs.fetchState
|
|
924
933
|
| _ =>
|
|
@@ -999,6 +1008,34 @@ let isInReorgThreshold = (cs: t) => cs.isInReorgThreshold
|
|
|
999
1008
|
// progress has run.
|
|
1000
1009
|
let shouldSaveHistory = (cs: t) =>
|
|
1001
1010
|
cs.shouldRollbackOnReorg && cs.maxReorgDepth > 0 && cs.isInReorgThreshold
|
|
1011
|
+
// What crossing into the recent blocks changed for this chain. Until now it
|
|
1012
|
+
// stopped short of the head by its reorg depth, because it kept nothing it
|
|
1013
|
+
// could roll back with; crossing lifts both at once. The second half is the
|
|
1014
|
+
// answer to why the indexer starts writing more than it was.
|
|
1015
|
+
// Whether crossing gives this chain anything more to index: the last block it
|
|
1016
|
+
// may fetch afterwards against the last it may fetch now. Read before the
|
|
1017
|
+
// crossing, while the lag being lifted is still the one in place.
|
|
1018
|
+
//
|
|
1019
|
+
// False wherever the lag was never holding this chain back, which is every
|
|
1020
|
+
// configuration that also keeps no history: a chain that isn't rolled back on a
|
|
1021
|
+
// reorg, or has no reorg depth, already fetches as far as it ever will. It is
|
|
1022
|
+
// false too for a chain whose end block sits below the blocks being opened up,
|
|
1023
|
+
// which will never reach one of them.
|
|
1024
|
+
let reorgThresholdLiftsCeiling = (cs: t) => {
|
|
1025
|
+
let ceiling = (~blockLag) => {
|
|
1026
|
+
let head = Pervasives.max(0, cs.fetchState.knownHeight - blockLag)
|
|
1027
|
+
switch cs.fetchState.endBlock {
|
|
1028
|
+
| Some(endBlock) => Pervasives.min(endBlock, head)
|
|
1029
|
+
| None => head
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
ceiling(~blockLag=cs.chainConfig.blockLag) > ceiling(~blockLag=cs.fetchState.blockLag)
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// Only ever said by a chain the crossing lifts, and lifting it takes a reorg
|
|
1036
|
+
// depth to have been held back by, which is the same thing that makes the
|
|
1037
|
+
// history below worth keeping. So there is no second form without it.
|
|
1038
|
+
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."
|
|
1002
1039
|
|
|
1003
1040
|
// Snapshot the chain's metadata fields for staging into the chains table.
|
|
1004
1041
|
let toChainMetadata = (cs: t): InternalTable.Chains.metaFields => {
|
|
@@ -1090,9 +1127,7 @@ let toChainBeforeBatch = (cs: t, ~isRealtime): Batch.chainBeforeBatch => {
|
|
|
1090
1127
|
// batch would leave it. Entering the threshold is what lifts the pre-threshold
|
|
1091
1128
|
// lag, so a chain waiting to enter it has fetched as far as it can.
|
|
1092
1129
|
let isReadyToEnterReorgThreshold = (cs: t) =>
|
|
1093
|
-
cs.fetchState->FetchState.isReadyToEnterReorgThreshold(
|
|
1094
|
-
~tolerance=cs.reorgThresholdReadyTolerance,
|
|
1095
|
-
)
|
|
1130
|
+
cs.fetchState->FetchState.isReadyToEnterReorgThreshold(~tolerance=cs.reorgThresholdReadyTolerance)
|
|
1096
1131
|
|
|
1097
1132
|
let isReadyToEnterReorgThresholdAfterBatch = (cs: t, ~batch: Batch.t) => {
|
|
1098
1133
|
let fetchState = switch batch.progressedChainsById->ChainId.Dict.dangerouslyGetNonOption(
|
|
@@ -1242,6 +1277,7 @@ let markReady = (cs: t, ~readyAt) =>
|
|
|
1242
1277
|
let rollbackCommittedProgress = (cs: t, blockNumber) =>
|
|
1243
1278
|
if blockNumber !== cs.committedProgressBlockNumber {
|
|
1244
1279
|
cs.committedProgressBlockNumber = blockNumber
|
|
1280
|
+
|
|
1245
1281
|
// Exact block only: the rolled-back region is about to be refetched, and
|
|
1246
1282
|
// the next batch re-establishes the time either way.
|
|
1247
1283
|
cs.committedProgressBlockTime =
|