envio 3.3.0-alpha.8 → 3.3.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/index.d.ts +19 -0
- package/licenses/CLA.md +35 -0
- package/licenses/EULA.md +67 -0
- package/licenses/LICENSE.md +45 -0
- package/licenses/README.md +35 -0
- package/package.json +9 -8
- package/src/Batch.res.mjs +1 -1
- package/src/BatchProcessing.res +0 -7
- package/src/BatchProcessing.res.mjs +1 -8
- package/src/ChainFetching.res +30 -18
- package/src/ChainFetching.res.mjs +23 -13
- package/src/ChainState.res +205 -59
- package/src/ChainState.res.mjs +130 -27
- package/src/ChainState.resi +16 -1
- package/src/Config.res +9 -5
- package/src/Config.res.mjs +2 -2
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +147 -39
- package/src/CrossChainState.res.mjs +42 -10
- package/src/EffectState.res +100 -0
- package/src/EffectState.res.mjs +74 -0
- package/src/EffectState.resi +32 -0
- package/src/Envio.res +25 -7
- package/src/Envio.res.mjs +15 -19
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +30 -56
- package/src/EventConfigBuilder.res.mjs +24 -30
- package/src/EventProcessing.res +8 -5
- package/src/EventProcessing.res.mjs +2 -1
- package/src/FetchState.res +842 -474
- package/src/FetchState.res.mjs +545 -356
- package/src/HandlerLoader.res +1 -1
- package/src/HandlerLoader.res.mjs +1 -1
- package/src/HandlerRegister.res +478 -305
- package/src/HandlerRegister.res.mjs +277 -209
- package/src/HandlerRegister.resi +11 -6
- package/src/InMemoryStore.res +14 -26
- package/src/InMemoryStore.res.mjs +6 -19
- package/src/IndexerState.res +15 -39
- package/src/IndexerState.res.mjs +18 -29
- package/src/IndexerState.resi +2 -10
- package/src/Internal.res +121 -18
- package/src/Internal.res.mjs +96 -2
- package/src/LoadLayer.res +44 -24
- package/src/LoadLayer.res.mjs +43 -20
- package/src/LoadLayer.resi +1 -0
- package/src/LogSelection.res +92 -217
- package/src/LogSelection.res.mjs +95 -184
- package/src/Main.res +29 -143
- package/src/Main.res.mjs +25 -88
- package/src/Metrics.res +1 -1
- package/src/Metrics.res.mjs +1 -1
- package/src/Persistence.res +12 -3
- package/src/PgStorage.res +155 -82
- package/src/PgStorage.res.mjs +130 -77
- package/src/Prometheus.res +20 -10
- package/src/Prometheus.res.mjs +22 -10
- package/src/PruneStaleHistory.res +146 -35
- package/src/PruneStaleHistory.res.mjs +114 -20
- package/src/RawEvent.res +2 -2
- package/src/Rollback.res +32 -13
- package/src/Rollback.res.mjs +24 -11
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +1 -1
- package/src/SimulateItems.res +39 -7
- package/src/SimulateItems.res.mjs +28 -9
- package/src/TestIndexer.res +2 -2
- package/src/TestIndexer.res.mjs +2 -2
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/UserContext.res +62 -23
- package/src/UserContext.res.mjs +26 -6
- package/src/Writing.res +60 -21
- package/src/Writing.res.mjs +27 -9
- package/src/bindings/NodeJs.res +5 -0
- package/src/bindings/Viem.res +0 -5
- package/src/sources/EventRouter.res +0 -21
- package/src/sources/EventRouter.res.mjs +0 -12
- package/src/sources/Evm.res +4 -1
- package/src/sources/Evm.res.mjs +1 -1
- package/src/sources/EvmChain.res +2 -27
- package/src/sources/EvmChain.res.mjs +2 -23
- package/src/sources/EvmRpcClient.res +58 -23
- package/src/sources/EvmRpcClient.res.mjs +11 -5
- package/src/sources/Fuel.res +3 -1
- package/src/sources/Fuel.res.mjs +1 -1
- package/src/sources/HyperSync.res +9 -38
- package/src/sources/HyperSync.res.mjs +16 -28
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +88 -11
- package/src/sources/HyperSyncClient.res.mjs +39 -6
- package/src/sources/HyperSyncSource.res +18 -210
- package/src/sources/HyperSyncSource.res.mjs +9 -137
- package/src/sources/Rpc.res +0 -32
- package/src/sources/Rpc.res.mjs +1 -46
- package/src/sources/RpcSource.res +129 -533
- package/src/sources/RpcSource.res.mjs +161 -379
- package/src/sources/SimulateSource.res +37 -19
- package/src/sources/SimulateSource.res.mjs +27 -10
- package/src/sources/SourceManager.res +4 -14
- package/src/sources/SourceManager.res.mjs +3 -9
- package/src/sources/SourceManager.resi +0 -2
- package/src/sources/SvmHyperSyncSource.res +13 -3
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
package/src/ChainState.res
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
type t = {
|
|
6
6
|
logger: Pino.t,
|
|
7
|
+
// The registrations used to build this chain's sources and route native items.
|
|
8
|
+
onEventRegistrations: array<Internal.onEventRegistration>,
|
|
7
9
|
mutable fetchState: FetchState.t,
|
|
8
10
|
// The chain-wide address index. Not `mutable`: the dict is mutated in place by
|
|
9
11
|
// register/rollback, so the reference is stable across fetchState versions.
|
|
@@ -13,8 +15,13 @@ type t = {
|
|
|
13
15
|
mutable isProgressAtHead: bool,
|
|
14
16
|
mutable timestampCaughtUpToHeadOrEndblock: option<Date.t>,
|
|
15
17
|
mutable committedProgressBlockNumber: int,
|
|
18
|
+
// Progress of the batch currently being processed. The buffer is consumed at
|
|
19
|
+
// batch creation (see advanceAfterBatch), so this runs ahead of
|
|
20
|
+
// committedProgressBlockNumber until the batch commits — it's the true lower
|
|
21
|
+
// boundary of the remaining buffer's block span.
|
|
22
|
+
mutable processingBlockNumber: int,
|
|
16
23
|
mutable numEventsProcessed: float,
|
|
17
|
-
// Running sum of in-flight queries'
|
|
24
|
+
// Running sum of in-flight queries' itemsEst, kept here so the
|
|
18
25
|
// scheduler doesn't re-sum pending queries on every tick. Incremented when
|
|
19
26
|
// queries are dispatched, decremented as their responses land.
|
|
20
27
|
mutable pendingBudget: float,
|
|
@@ -66,9 +73,22 @@ let configAddresses = (chainConfig: Config.chain): array<Internal.indexingAddres
|
|
|
66
73
|
addresses
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
let validateOnEventRegistrations = (
|
|
77
|
+
~chainId: int,
|
|
78
|
+
registrations: array<Internal.onEventRegistration>,
|
|
79
|
+
) =>
|
|
80
|
+
registrations->Array.forEachWithIndex((registration, expectedIndex) => {
|
|
81
|
+
if registration.index !== expectedIndex {
|
|
82
|
+
JsError.throwWithMessage(
|
|
83
|
+
`Invalid onEvent registration index for chain ${chainId->Int.toString}: ${registration.eventConfig.contractName}.${registration.eventConfig.name} has index ${registration.index->Int.toString}, but its ChainState position is ${expectedIndex->Int.toString}.`,
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
69
88
|
let make = (
|
|
70
89
|
~chainConfig: Config.chain,
|
|
71
90
|
~fetchState: FetchState.t,
|
|
91
|
+
~onEventRegistrations=[],
|
|
72
92
|
~indexingAddresses: IndexingAddresses.t,
|
|
73
93
|
~sourceManager: SourceManager.t,
|
|
74
94
|
~reorgDetection: ReorgDetection.t,
|
|
@@ -82,21 +102,26 @@ let make = (
|
|
|
82
102
|
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm, ~shouldChecksum=false),
|
|
83
103
|
~logger: Pino.t,
|
|
84
104
|
): t => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
validateOnEventRegistrations(~chainId=chainConfig.id, onEventRegistrations)
|
|
106
|
+
{
|
|
107
|
+
logger,
|
|
108
|
+
onEventRegistrations,
|
|
109
|
+
fetchState,
|
|
110
|
+
indexingAddresses,
|
|
111
|
+
sourceManager,
|
|
112
|
+
chainConfig,
|
|
113
|
+
isProgressAtHead,
|
|
114
|
+
timestampCaughtUpToHeadOrEndblock,
|
|
115
|
+
committedProgressBlockNumber,
|
|
116
|
+
processingBlockNumber: committedProgressBlockNumber,
|
|
117
|
+
numEventsProcessed,
|
|
118
|
+
pendingBudget: 0.,
|
|
119
|
+
chainDensity,
|
|
120
|
+
reorgDetection,
|
|
121
|
+
safeCheckpointTracking,
|
|
122
|
+
transactionStore,
|
|
123
|
+
blockStore,
|
|
124
|
+
}
|
|
100
125
|
}
|
|
101
126
|
|
|
102
127
|
let makeInternal = (
|
|
@@ -136,25 +161,6 @@ let makeInternal = (
|
|
|
136
161
|
}
|
|
137
162
|
})
|
|
138
163
|
|
|
139
|
-
// TODO: Move it to the HandlerRegister module
|
|
140
|
-
// so the error is thrown with better stack trace
|
|
141
|
-
onBlockRegistrations->Array.forEach(onBlockRegistration => {
|
|
142
|
-
if onBlockRegistration.startBlock->Option.getOr(startBlock) < startBlock {
|
|
143
|
-
JsError.throwWithMessage(
|
|
144
|
-
`The start block for onBlock handler "${onBlockRegistration.name}" is less than the chain start block (${startBlock->Int.toString}). This is not supported yet.`,
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
switch endBlock {
|
|
148
|
-
| Some(chainEndBlock) =>
|
|
149
|
-
if onBlockRegistration.endBlock->Option.getOr(chainEndBlock) > chainEndBlock {
|
|
150
|
-
JsError.throwWithMessage(
|
|
151
|
-
`The end block for onBlock handler "${onBlockRegistration.name}" is greater than the chain end block (${chainEndBlock->Int.toString}). This is not supported yet.`,
|
|
152
|
-
)
|
|
153
|
-
}
|
|
154
|
-
| None => ()
|
|
155
|
-
}
|
|
156
|
-
})
|
|
157
|
-
|
|
158
164
|
let contractConfigs = IndexingAddresses.makeContractConfigs(~onEventRegistrations)
|
|
159
165
|
let indexingAddressIndex = IndexingAddresses.make(~contractConfigs, ~addresses=indexingAddresses)
|
|
160
166
|
|
|
@@ -251,6 +257,7 @@ let makeInternal = (
|
|
|
251
257
|
make(
|
|
252
258
|
~chainConfig,
|
|
253
259
|
~fetchState,
|
|
260
|
+
~onEventRegistrations,
|
|
254
261
|
~indexingAddresses=indexingAddressIndex,
|
|
255
262
|
~sourceManager=SourceManager.make(~sources, ~isRealtime, ~reducedPollingInterval?),
|
|
256
263
|
~reorgDetection=ReorgDetection.make(
|
|
@@ -385,7 +392,8 @@ let isReadyToEnterReorgThreshold = (cs: t) => cs.fetchState->FetchState.isReadyT
|
|
|
385
392
|
let startFetchingQueries = (cs: t, ~queries: array<FetchState.query>) => {
|
|
386
393
|
cs.fetchState->FetchState.startFetchingQueries(~queries)
|
|
387
394
|
cs.pendingBudget =
|
|
388
|
-
cs.pendingBudget +.
|
|
395
|
+
cs.pendingBudget +.
|
|
396
|
+
queries->Array.reduce(0., (acc, query) => acc +. query.itemsEst->Int.toFloat)
|
|
389
397
|
}
|
|
390
398
|
|
|
391
399
|
// Drop every in-flight query and release their reservations together, keeping
|
|
@@ -395,24 +403,150 @@ let resetPendingQueries = (cs: t) => {
|
|
|
395
403
|
cs.pendingBudget = 0.
|
|
396
404
|
}
|
|
397
405
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
let
|
|
406
|
+
let isReady = (cs: t) => cs.timestampCaughtUpToHeadOrEndblock !== None
|
|
407
|
+
|
|
408
|
+
// Block span over which a batch fully replaces the chain density estimate;
|
|
409
|
+
// smaller batches blend in proportionally, so a few sparse/dense blocks only
|
|
410
|
+
// nudge it.
|
|
411
|
+
let densityBlendWindow = 100.
|
|
412
|
+
|
|
413
|
+
// The last block this chain can fetch right now: the lagged head
|
|
414
|
+
// (knownHeight - blockLag, the frontier when a reorg-threshold blockLag holds
|
|
415
|
+
// back the tip), or endBlock when it's below that head. Matching isFetchingAtHead's
|
|
416
|
+
// definition of the head is what lets a chain parked at its lagged head read
|
|
417
|
+
// 100% progress instead of looking behind against blocks it can't fetch.
|
|
418
|
+
let fetchCeiling = (cs: t) => {
|
|
419
|
+
let fetchState = cs.fetchState
|
|
420
|
+
let head = Pervasives.max(0, fetchState.knownHeight - fetchState.blockLag)
|
|
421
|
+
switch fetchState.endBlock {
|
|
422
|
+
| Some(endBlock) => Pervasives.min(endBlock, head)
|
|
423
|
+
| None => head
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Events/block over the ready part of the buffer — a live signal that reacts
|
|
428
|
+
// to what fetching just found, unlike the processing EMA which only moves as
|
|
429
|
+
// batches commit.
|
|
430
|
+
let readyBufferDensity = (cs: t) => {
|
|
431
|
+
let readyCount = cs.fetchState->FetchState.bufferReadyCount
|
|
432
|
+
let span = cs.fetchState->FetchState.bufferBlockNumber - cs.processingBlockNumber
|
|
433
|
+
if readyCount > 0 && span > 0 {
|
|
434
|
+
Some(readyCount->Int.toFloat /. span->Int.toFloat)
|
|
435
|
+
} else {
|
|
436
|
+
None
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Density used for query sizing: the higher of the processing EMA and the
|
|
441
|
+
// ready-buffer density, so a stale-low EMA can't undersize queries while the
|
|
442
|
+
// buffer proves the range is dense. None means the chain is cold — no density
|
|
443
|
+
// signal at all.
|
|
444
|
+
let effectiveDensity = (cs: t) =>
|
|
445
|
+
switch (cs.chainDensity, cs->readyBufferDensity) {
|
|
446
|
+
| (Some(ema), Some(buffer)) => Some(Pervasives.max(ema, buffer))
|
|
447
|
+
| (Some(_) as density, None) | (None, Some(_) as density) => density
|
|
448
|
+
| (None, None) => None
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// How far past the frontier a chain with no density signal targets while it
|
|
452
|
+
// takes its first measurements.
|
|
453
|
+
let coldTargetRange = 20_000
|
|
454
|
+
|
|
455
|
+
// This chain's share of the indexer-wide buffer budget turned into a soft
|
|
456
|
+
// target block: via density, or frontier + coldTargetRange when there's no
|
|
457
|
+
// density signal yet.
|
|
458
|
+
let targetBlock = (cs: t, ~chainTargetItems: float) => {
|
|
404
459
|
let fetchState = cs.fetchState
|
|
405
|
-
let
|
|
460
|
+
let fetchCeiling = cs->fetchCeiling
|
|
406
461
|
let bufferBlockNumber = fetchState->FetchState.bufferBlockNumber
|
|
407
|
-
|
|
462
|
+
switch cs->effectiveDensity {
|
|
408
463
|
| Some(density) if density > 0. =>
|
|
409
464
|
Pervasives.min(
|
|
410
|
-
|
|
465
|
+
fetchCeiling,
|
|
411
466
|
bufferBlockNumber + Math.ceil(chainTargetItems /. density)->Float.toInt,
|
|
412
467
|
)
|
|
413
|
-
| _ =>
|
|
468
|
+
| _ => Pervasives.min(bufferBlockNumber + coldTargetRange, fetchCeiling)
|
|
414
469
|
}
|
|
415
|
-
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Block range that cross-chain progress alignment maps fractions over: from
|
|
473
|
+
// the chain's startBlock to the last block it can fetch right now. The lower
|
|
474
|
+
// bound is deliberately static — anchoring it at firstEventBlock would make
|
|
475
|
+
// two chains sitting at the same block read different progress fractions
|
|
476
|
+
// depending on whether each has discovered its first event yet, so the
|
|
477
|
+
// anchor's line could map below a follower's own frontier and stall it.
|
|
478
|
+
let progressRange = (cs: t) => {
|
|
479
|
+
let fetchState = cs.fetchState
|
|
480
|
+
(fetchState.startBlock, cs->fetchCeiling)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// A degenerate range (chain already at or past its last block) maps to 1 so it
|
|
484
|
+
// never constrains the other chains. Clamped at 0 for the initial -1 fetch
|
|
485
|
+
// frontier — the only possible blockNumber below the range's lower bound.
|
|
486
|
+
let progressAtBlock = (cs: t, ~blockNumber) => {
|
|
487
|
+
let (lower, upper) = cs->progressRange
|
|
488
|
+
upper <= lower
|
|
489
|
+
? 1.
|
|
490
|
+
: Pervasives.max(
|
|
491
|
+
0.,
|
|
492
|
+
Pervasives.min(1., (blockNumber - lower)->Int.toFloat /. (upper - lower)->Int.toFloat),
|
|
493
|
+
)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
let blockAtProgress = (cs: t, ~progress) => {
|
|
497
|
+
let (lower, upper) = cs->progressRange
|
|
498
|
+
lower + Math.ceil(progress *. (upper - lower)->Int.toFloat)->Float.toInt
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// The fetch frontier as a fraction of the alignable range — what the
|
|
502
|
+
// cross-chain waterfall aligns other chains against. Based on blocks actually
|
|
503
|
+
// fetched, so it holds up even while this chain's queries are in flight.
|
|
504
|
+
let frontierProgress = (cs: t) =>
|
|
505
|
+
cs->progressAtBlock(~blockNumber=cs.fetchState->FetchState.bufferBlockNumber)
|
|
506
|
+
|
|
507
|
+
// Propose queries sized against this chain's target block. Called by
|
|
508
|
+
// CrossChainState's waterfall, furthest-behind chain first, with
|
|
509
|
+
// chainTargetItems set to whatever budget remains at that point and
|
|
510
|
+
// maxTargetBlock set to the most-behind chain's progress mapped onto this
|
|
511
|
+
// chain, so a chain with budget can't run further ahead than the chain the
|
|
512
|
+
// whole pool is prioritizing.
|
|
513
|
+
let getNextQuery = (
|
|
514
|
+
cs: t,
|
|
515
|
+
~chainTargetItems: float,
|
|
516
|
+
~chunkItemsMultiplier=1.,
|
|
517
|
+
~itemsTargetFloor=0,
|
|
518
|
+
~maxTargetBlock=?,
|
|
519
|
+
) => {
|
|
520
|
+
let chainTargetBlock = cs->targetBlock(~chainTargetItems)
|
|
521
|
+
let chainTargetBlock = switch maxTargetBlock {
|
|
522
|
+
| Some(maxTargetBlock) => Pervasives.min(chainTargetBlock, maxTargetBlock)
|
|
523
|
+
| None => chainTargetBlock
|
|
524
|
+
}
|
|
525
|
+
// When the target block is clamped (head/endBlock/cross-chain alignment) a
|
|
526
|
+
// known-density chain can't use the whole handed budget — cap the fresh part
|
|
527
|
+
// at what the clamped range actually costs (in-flight reservations stay on
|
|
528
|
+
// top: they're already accounted and shouldn't crowd out new partitions), so
|
|
529
|
+
// the waterfall's leftover flows to the next chain in the same tick instead
|
|
530
|
+
// of being held by an oversized probe.
|
|
531
|
+
let chainTargetItems = switch cs->effectiveDensity {
|
|
532
|
+
| Some(density) if density > 0. =>
|
|
533
|
+
// No extra headroom here: the budget is reserved in honest itemsEst units,
|
|
534
|
+
// and truncation safety lives in the itemsTarget server cap (sized with
|
|
535
|
+
// chunkItemsMultiplier at query creation) — multiplying the budget cap too
|
|
536
|
+
// would compound the two and hold budget away from other chains.
|
|
537
|
+
let rangeCost =
|
|
538
|
+
density *. (chainTargetBlock - cs.fetchState->FetchState.bufferBlockNumber)->Int.toFloat
|
|
539
|
+
Pervasives.min(chainTargetItems, Math.ceil(rangeCost) +. cs.pendingBudget)
|
|
540
|
+
// No density signal: the cross-chain waterfall already clamped the handed
|
|
541
|
+
// budget to the cold-chain cap, so it's used as-is.
|
|
542
|
+
| _ => chainTargetItems
|
|
543
|
+
}
|
|
544
|
+
cs.fetchState->FetchState.getNextQuery(
|
|
545
|
+
~chainTargetBlock,
|
|
546
|
+
~chainTargetItems,
|
|
547
|
+
~chunkItemsMultiplier,
|
|
548
|
+
~itemsTargetFloor,
|
|
549
|
+
)
|
|
416
550
|
}
|
|
417
551
|
|
|
418
552
|
// Run a fetch tick for this chain against its sources, feeding the owned fetch
|
|
@@ -451,8 +585,6 @@ let getHighestBlockBelowThreshold = (cs: t): int => {
|
|
|
451
585
|
|
|
452
586
|
let isActivelyIndexing = (cs: t) => cs.fetchState->FetchState.isActivelyIndexing
|
|
453
587
|
|
|
454
|
-
let isReady = (cs: t) => cs.timestampCaughtUpToHeadOrEndblock !== None
|
|
455
|
-
|
|
456
588
|
// True once the fetch frontier has reached the head/endBlock for this chain.
|
|
457
589
|
let isFetchingAtHead = (cs: t) => cs.fetchState->FetchState.isFetchingAtHead
|
|
458
590
|
|
|
@@ -648,6 +780,9 @@ let materializePageItems = async (
|
|
|
648
780
|
))
|
|
649
781
|
}
|
|
650
782
|
|
|
783
|
+
let filterByClientAddress = (cs: t, items: array<Internal.item>): array<Internal.item> =>
|
|
784
|
+
items->FetchState.filterByClientAddress(~indexingAddresses=cs.indexingAddresses)
|
|
785
|
+
|
|
651
786
|
let handleQueryResult = (
|
|
652
787
|
cs: t,
|
|
653
788
|
~query: FetchState.query,
|
|
@@ -680,16 +815,11 @@ let handleQueryResult = (
|
|
|
680
815
|
|
|
681
816
|
cs.fetchState =
|
|
682
817
|
fs
|
|
683
|
-
->FetchState.handleQueryResult(
|
|
684
|
-
~indexingAddresses=cs.indexingAddresses,
|
|
685
|
-
~query,
|
|
686
|
-
~latestFetchedBlock,
|
|
687
|
-
~newItems,
|
|
688
|
-
)
|
|
818
|
+
->FetchState.handleQueryResult(~query, ~latestFetchedBlock, ~newItems)
|
|
689
819
|
->FetchState.updateKnownHeight(~knownHeight)
|
|
690
820
|
|
|
691
821
|
// The query is no longer in flight, so release its reservation.
|
|
692
|
-
cs.pendingBudget = Pervasives.max(0., cs.pendingBudget -. query.
|
|
822
|
+
cs.pendingBudget = Pervasives.max(0., cs.pendingBudget -. query.itemsEst->Int.toFloat)
|
|
693
823
|
}
|
|
694
824
|
|
|
695
825
|
// Run reorg detection against a fetch response and commit the updated guard.
|
|
@@ -790,6 +920,10 @@ let advanceAfterBatch = (cs: t, ~batch: Batch.t, ~enteringReorgThreshold) =>
|
|
|
790
920
|
cs.fetchState = enteringReorgThreshold
|
|
791
921
|
? chainAfterBatch.fetchState->FetchState.updateInternal(~blockLag=cs.chainConfig.blockLag)
|
|
792
922
|
: chainAfterBatch.fetchState
|
|
923
|
+
|
|
924
|
+
// The batch's items just left the buffer, so the remaining buffer's span
|
|
925
|
+
// starts at the batch's progress.
|
|
926
|
+
cs.processingBlockNumber = chainAfterBatch.progressBlockNumber
|
|
793
927
|
| None => ()
|
|
794
928
|
}
|
|
795
929
|
|
|
@@ -852,8 +986,9 @@ let applyBatchProgress = (cs: t, ~batch: Batch.t, ~blockTimestampName: string) =
|
|
|
852
986
|
}
|
|
853
987
|
|
|
854
988
|
// Chain-wide density update: seed with the batch's own events/block on
|
|
855
|
-
// the first update, then
|
|
856
|
-
// sparse/dense blocks
|
|
989
|
+
// the first update, then blend weighted by the batch's block span — a
|
|
990
|
+
// few sparse/dense blocks barely nudge the estimate, while a
|
|
991
|
+
// window-sized batch replaces it.
|
|
857
992
|
let deltaBlocks = chainAfterBatch.progressBlockNumber - cs.committedProgressBlockNumber
|
|
858
993
|
if deltaBlocks > 0 {
|
|
859
994
|
let deltaEvents = chainAfterBatch.totalEventsProcessed -. cs.numEventsProcessed
|
|
@@ -866,13 +1001,22 @@ let applyBatchProgress = (cs: t, ~batch: Batch.t, ~blockTimestampName: string) =
|
|
|
866
1001
|
cs.chainDensity = Some(
|
|
867
1002
|
switch cs.chainDensity {
|
|
868
1003
|
| None => batchDensity
|
|
869
|
-
| Some(oldDensity) =>
|
|
1004
|
+
| Some(oldDensity) =>
|
|
1005
|
+
let alpha = Pervasives.min(1., deltaBlocks->Int.toFloat /. densityBlendWindow)
|
|
1006
|
+
oldDensity *. (1. -. alpha) +. batchDensity *. alpha
|
|
870
1007
|
},
|
|
871
1008
|
)
|
|
872
1009
|
}
|
|
873
1010
|
}
|
|
874
1011
|
|
|
875
1012
|
cs.committedProgressBlockNumber = chainAfterBatch.progressBlockNumber
|
|
1013
|
+
|
|
1014
|
+
// Normally already set by advanceAfterBatch at batch creation; catch up
|
|
1015
|
+
// here for paths that commit progress without it.
|
|
1016
|
+
cs.processingBlockNumber = Pervasives.max(
|
|
1017
|
+
cs.processingBlockNumber,
|
|
1018
|
+
chainAfterBatch.progressBlockNumber,
|
|
1019
|
+
)
|
|
876
1020
|
cs.numEventsProcessed = chainAfterBatch.totalEventsProcessed
|
|
877
1021
|
// Processed blocks' transactions and blocks are no longer needed.
|
|
878
1022
|
cs.transactionStore->TransactionStore.prune(chainAfterBatch.progressBlockNumber)
|
|
@@ -957,6 +1101,7 @@ let rollback = (
|
|
|
957
1101
|
cs.transactionStore->TransactionStore.rollback(newProgressBlockNumber)
|
|
958
1102
|
cs.blockStore->BlockStore.rollback(newProgressBlockNumber)
|
|
959
1103
|
cs.committedProgressBlockNumber = newProgressBlockNumber
|
|
1104
|
+
cs.processingBlockNumber = newProgressBlockNumber
|
|
960
1105
|
cs.numEventsProcessed = newTotalEventsProcessed
|
|
961
1106
|
| None =>
|
|
962
1107
|
if isReorgChain {
|
|
@@ -975,6 +1120,7 @@ let rollback = (
|
|
|
975
1120
|
cs.committedProgressBlockNumber,
|
|
976
1121
|
rollbackTargetBlockNumber,
|
|
977
1122
|
)
|
|
1123
|
+
cs.processingBlockNumber = Pervasives.min(cs.processingBlockNumber, rollbackTargetBlockNumber)
|
|
978
1124
|
}
|
|
979
1125
|
}
|
|
980
1126
|
}
|
package/src/ChainState.res.mjs
CHANGED
|
@@ -40,7 +40,16 @@ function configAddresses(chainConfig) {
|
|
|
40
40
|
return addresses;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function
|
|
43
|
+
function validateOnEventRegistrations(chainId, registrations) {
|
|
44
|
+
registrations.forEach((registration, expectedIndex) => {
|
|
45
|
+
if (registration.index !== expectedIndex) {
|
|
46
|
+
return Stdlib_JsError.throwWithMessage(`Invalid onEvent registration index for chain ` + chainId.toString() + `: ` + registration.eventConfig.contractName + `.` + registration.eventConfig.name + ` has index ` + registration.index.toString() + `, but its ChainState position is ` + expectedIndex.toString() + `.`);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function make(chainConfig, fetchState, onEventRegistrationsOpt, indexingAddresses, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, logger) {
|
|
52
|
+
let onEventRegistrations = onEventRegistrationsOpt !== undefined ? onEventRegistrationsOpt : [];
|
|
44
53
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
45
54
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
46
55
|
let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
|
|
@@ -48,8 +57,10 @@ function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDe
|
|
|
48
57
|
let transactionStore = transactionStoreOpt !== undefined ? Primitive_option.valFromOption(transactionStoreOpt) : TransactionStore.make("evm", false);
|
|
49
58
|
let chainDensity = chainDensityOpt !== undefined ? Primitive_option.valFromOption(chainDensityOpt) : undefined;
|
|
50
59
|
let blockStore = blockStoreOpt !== undefined ? Primitive_option.valFromOption(blockStoreOpt) : BlockStore.make("evm", false);
|
|
60
|
+
validateOnEventRegistrations(chainConfig.id, onEventRegistrations);
|
|
51
61
|
return {
|
|
52
62
|
logger: logger,
|
|
63
|
+
onEventRegistrations: onEventRegistrations,
|
|
53
64
|
fetchState: fetchState,
|
|
54
65
|
indexingAddresses: indexingAddresses,
|
|
55
66
|
sourceManager: sourceManager,
|
|
@@ -57,6 +68,7 @@ function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDe
|
|
|
57
68
|
isProgressAtHead: isProgressAtHead,
|
|
58
69
|
timestampCaughtUpToHeadOrEndblock: timestampCaughtUpToHeadOrEndblock,
|
|
59
70
|
committedProgressBlockNumber: committedProgressBlockNumber,
|
|
71
|
+
processingBlockNumber: committedProgressBlockNumber,
|
|
60
72
|
numEventsProcessed: numEventsProcessed,
|
|
61
73
|
pendingBudget: 0,
|
|
62
74
|
chainDensity: chainDensity,
|
|
@@ -74,7 +86,6 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
74
86
|
onEventRegistrations: [],
|
|
75
87
|
onBlockRegistrations: []
|
|
76
88
|
});
|
|
77
|
-
let onBlockRegistrations = match.onBlockRegistrations;
|
|
78
89
|
let onEventRegistrations = match.onEventRegistrations;
|
|
79
90
|
chainConfig.contracts.forEach(contract => {
|
|
80
91
|
let startBlock = contract.startBlock;
|
|
@@ -82,17 +93,9 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
82
93
|
return Stdlib_JsError.throwWithMessage(`The start block for contract "` + contract.name + `" is less than the chain start block. This is not supported yet.`);
|
|
83
94
|
}
|
|
84
95
|
});
|
|
85
|
-
onBlockRegistrations.forEach(onBlockRegistration => {
|
|
86
|
-
if (Stdlib_Option.getOr(onBlockRegistration.startBlock, startBlock) < startBlock) {
|
|
87
|
-
Stdlib_JsError.throwWithMessage(`The start block for onBlock handler "` + onBlockRegistration.name + `" is less than the chain start block (` + startBlock.toString() + `). This is not supported yet.`);
|
|
88
|
-
}
|
|
89
|
-
if (endBlock !== undefined && Stdlib_Option.getOr(onBlockRegistration.endBlock, endBlock) > endBlock) {
|
|
90
|
-
return Stdlib_JsError.throwWithMessage(`The end block for onBlock handler "` + onBlockRegistration.name + `" is greater than the chain end block (` + endBlock.toString() + `). This is not supported yet.`);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
96
|
let contractConfigs = IndexingAddresses.makeContractConfigs(onEventRegistrations);
|
|
94
97
|
let indexingAddressIndex = IndexingAddresses.make(contractConfigs, indexingAddresses);
|
|
95
|
-
let fetchState = FetchState.make(startBlock, endBlock, onEventRegistrations, contractConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, onBlockRegistrations, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
|
|
98
|
+
let fetchState = FetchState.make(startBlock, endBlock, onEventRegistrations, contractConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, match.onBlockRegistrations, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
|
|
96
99
|
let chainReorgCheckpoints = Stdlib_Array.filterMap(reorgCheckpoints, reorgCheckpoint => {
|
|
97
100
|
if (reorgCheckpoint.chain_id === chainConfig.id) {
|
|
98
101
|
return reorgCheckpoint;
|
|
@@ -144,7 +147,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
144
147
|
}
|
|
145
148
|
let firstEventBlock$1 = fetchState.firstEventBlock;
|
|
146
149
|
let chainDensity = firstEventBlock$1 !== undefined && progressBlockNumber > firstEventBlock$1 && numEventsProcessed > 0 ? numEventsProcessed / (progressBlockNumber - firstEventBlock$1 | 0) : undefined;
|
|
147
|
-
return make(chainConfig, fetchState, indexingAddressIndex, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(BlockStore.make(config.ecosystem.name, !lowercaseAddresses)), logger);
|
|
150
|
+
return make(chainConfig, fetchState, onEventRegistrations, indexingAddressIndex, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(BlockStore.make(config.ecosystem.name, !lowercaseAddresses)), logger);
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
function makeFromConfig(chainConfig, config, registrationsByChainId, knownHeight) {
|
|
@@ -242,16 +245,100 @@ function isReadyToEnterReorgThreshold(cs) {
|
|
|
242
245
|
|
|
243
246
|
function startFetchingQueries(cs, queries) {
|
|
244
247
|
FetchState.startFetchingQueries(cs.fetchState, queries);
|
|
245
|
-
cs.pendingBudget = cs.pendingBudget + Stdlib_Array.reduce(queries, 0, (acc, query) => acc + query.
|
|
248
|
+
cs.pendingBudget = cs.pendingBudget + Stdlib_Array.reduce(queries, 0, (acc, query) => acc + query.itemsEst);
|
|
246
249
|
}
|
|
247
250
|
|
|
248
|
-
function
|
|
251
|
+
function isReady(cs) {
|
|
252
|
+
return cs.timestampCaughtUpToHeadOrEndblock !== undefined;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function fetchCeiling(cs) {
|
|
249
256
|
let fetchState = cs.fetchState;
|
|
250
|
-
let
|
|
257
|
+
let head = Primitive_int.max(0, fetchState.knownHeight - fetchState.blockLag | 0);
|
|
258
|
+
let endBlock = fetchState.endBlock;
|
|
259
|
+
if (endBlock !== undefined) {
|
|
260
|
+
return Primitive_int.min(endBlock, head);
|
|
261
|
+
} else {
|
|
262
|
+
return head;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function readyBufferDensity(cs) {
|
|
267
|
+
let readyCount = FetchState.bufferReadyCount(cs.fetchState);
|
|
268
|
+
let span = FetchState.bufferBlockNumber(cs.fetchState) - cs.processingBlockNumber | 0;
|
|
269
|
+
if (readyCount > 0 && span > 0) {
|
|
270
|
+
return readyCount / span;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function effectiveDensity(cs) {
|
|
275
|
+
let match = cs.chainDensity;
|
|
276
|
+
let match$1 = readyBufferDensity(cs);
|
|
277
|
+
if (match !== undefined) {
|
|
278
|
+
if (match$1 !== undefined) {
|
|
279
|
+
return Primitive_float.max(match, match$1);
|
|
280
|
+
} else {
|
|
281
|
+
return match;
|
|
282
|
+
}
|
|
283
|
+
} else if (match$1 !== undefined) {
|
|
284
|
+
return match$1;
|
|
285
|
+
} else {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function targetBlock(cs, chainTargetItems) {
|
|
291
|
+
let fetchState = cs.fetchState;
|
|
292
|
+
let fetchCeiling$1 = fetchCeiling(cs);
|
|
251
293
|
let bufferBlockNumber = FetchState.bufferBlockNumber(fetchState);
|
|
252
|
-
let density = cs
|
|
253
|
-
|
|
254
|
-
|
|
294
|
+
let density = effectiveDensity(cs);
|
|
295
|
+
if (density !== undefined && density > 0) {
|
|
296
|
+
return Primitive_int.min(fetchCeiling$1, bufferBlockNumber + (Math.ceil(chainTargetItems / density) | 0) | 0);
|
|
297
|
+
} else {
|
|
298
|
+
return Primitive_int.min(bufferBlockNumber + 20000 | 0, fetchCeiling$1);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function progressRange(cs) {
|
|
303
|
+
let fetchState = cs.fetchState;
|
|
304
|
+
return [
|
|
305
|
+
fetchState.startBlock,
|
|
306
|
+
fetchCeiling(cs)
|
|
307
|
+
];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function blockAtProgress(cs, progress) {
|
|
311
|
+
let match = progressRange(cs);
|
|
312
|
+
let lower = match[0];
|
|
313
|
+
return lower + (Math.ceil(progress * (match[1] - lower | 0)) | 0) | 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function frontierProgress(cs) {
|
|
317
|
+
let blockNumber = FetchState.bufferBlockNumber(cs.fetchState);
|
|
318
|
+
let match = progressRange(cs);
|
|
319
|
+
let upper = match[1];
|
|
320
|
+
let lower = match[0];
|
|
321
|
+
if (upper <= lower) {
|
|
322
|
+
return 1;
|
|
323
|
+
} else {
|
|
324
|
+
return Primitive_float.max(0, Primitive_float.min(1, (blockNumber - lower | 0) / (upper - lower | 0)));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function getNextQuery(cs, chainTargetItems, chunkItemsMultiplierOpt, itemsTargetFloorOpt, maxTargetBlock) {
|
|
329
|
+
let chunkItemsMultiplier = chunkItemsMultiplierOpt !== undefined ? chunkItemsMultiplierOpt : 1;
|
|
330
|
+
let itemsTargetFloor = itemsTargetFloorOpt !== undefined ? itemsTargetFloorOpt : 0;
|
|
331
|
+
let chainTargetBlock = targetBlock(cs, chainTargetItems);
|
|
332
|
+
let chainTargetBlock$1 = maxTargetBlock !== undefined ? Primitive_int.min(chainTargetBlock, maxTargetBlock) : chainTargetBlock;
|
|
333
|
+
let density = effectiveDensity(cs);
|
|
334
|
+
let chainTargetItems$1;
|
|
335
|
+
if (density !== undefined && density > 0) {
|
|
336
|
+
let rangeCost = density * (chainTargetBlock$1 - FetchState.bufferBlockNumber(cs.fetchState) | 0);
|
|
337
|
+
chainTargetItems$1 = Primitive_float.min(chainTargetItems, Math.ceil(rangeCost) + cs.pendingBudget);
|
|
338
|
+
} else {
|
|
339
|
+
chainTargetItems$1 = chainTargetItems;
|
|
340
|
+
}
|
|
341
|
+
return FetchState.getNextQuery(cs.fetchState, chainTargetBlock$1, chainTargetItems$1, chunkItemsMultiplier, itemsTargetFloor);
|
|
255
342
|
}
|
|
256
343
|
|
|
257
344
|
function dispatch(cs, executeQuery, waitForNewBlock, onNewBlock, action, stateId) {
|
|
@@ -282,10 +369,6 @@ function isActivelyIndexing(cs) {
|
|
|
282
369
|
return FetchState.isActivelyIndexing(cs.fetchState);
|
|
283
370
|
}
|
|
284
371
|
|
|
285
|
-
function isReady(cs) {
|
|
286
|
-
return cs.timestampCaughtUpToHeadOrEndblock !== undefined;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
372
|
function isFetchingAtHead(cs) {
|
|
290
373
|
return FetchState.isFetchingAtHead(cs.fetchState);
|
|
291
374
|
}
|
|
@@ -426,6 +509,10 @@ async function materializePageItems(items, transactionStore, blockStore, ecosyst
|
|
|
426
509
|
]);
|
|
427
510
|
}
|
|
428
511
|
|
|
512
|
+
function filterByClientAddress(cs, items) {
|
|
513
|
+
return FetchState.filterByClientAddress(items, cs.indexingAddresses);
|
|
514
|
+
}
|
|
515
|
+
|
|
429
516
|
function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight, txPage, blockPage) {
|
|
430
517
|
if (txPage !== undefined) {
|
|
431
518
|
cs.transactionStore.merge(Primitive_option.valFromOption(txPage));
|
|
@@ -434,8 +521,8 @@ function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBl
|
|
|
434
521
|
cs.blockStore.merge(Primitive_option.valFromOption(blockPage));
|
|
435
522
|
}
|
|
436
523
|
let fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.indexingAddresses, newItemsWithDcs) : cs.fetchState;
|
|
437
|
-
cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs,
|
|
438
|
-
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.
|
|
524
|
+
cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), knownHeight);
|
|
525
|
+
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.itemsEst);
|
|
439
526
|
}
|
|
440
527
|
|
|
441
528
|
function registerReorgGuard(cs, blockHashes, knownHeight) {
|
|
@@ -499,7 +586,7 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
|
|
|
499
586
|
}
|
|
500
587
|
|
|
501
588
|
function enterReorgThreshold(cs) {
|
|
502
|
-
cs.fetchState = FetchState.updateInternal(cs.fetchState, undefined, undefined, cs.chainConfig.blockLag, undefined);
|
|
589
|
+
cs.fetchState = FetchState.updateInternal(cs.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined);
|
|
503
590
|
}
|
|
504
591
|
|
|
505
592
|
function toChainMetadata(cs) {
|
|
@@ -547,7 +634,8 @@ function isReadyToEnterReorgThresholdAfterBatch(cs, batch) {
|
|
|
547
634
|
function advanceAfterBatch(cs, batch, enteringReorgThreshold) {
|
|
548
635
|
let chainAfterBatch = batch.progressedChainsById[cs.fetchState.chainId];
|
|
549
636
|
if (chainAfterBatch !== undefined) {
|
|
550
|
-
cs.fetchState = enteringReorgThreshold ? FetchState.updateInternal(chainAfterBatch.fetchState, undefined, undefined, cs.chainConfig.blockLag, undefined) : chainAfterBatch.fetchState;
|
|
637
|
+
cs.fetchState = enteringReorgThreshold ? FetchState.updateInternal(chainAfterBatch.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined) : chainAfterBatch.fetchState;
|
|
638
|
+
cs.processingBlockNumber = chainAfterBatch.progressBlockNumber;
|
|
551
639
|
return;
|
|
552
640
|
}
|
|
553
641
|
}
|
|
@@ -603,10 +691,18 @@ function applyBatchProgress(cs, batch, blockTimestampName) {
|
|
|
603
691
|
if (exit === 1) {
|
|
604
692
|
let batchDensity = deltaEvents / deltaBlocks;
|
|
605
693
|
let oldDensity = cs.chainDensity;
|
|
606
|
-
|
|
694
|
+
let tmp;
|
|
695
|
+
if (oldDensity !== undefined) {
|
|
696
|
+
let alpha = Primitive_float.min(1, deltaBlocks / 100);
|
|
697
|
+
tmp = oldDensity * (1 - alpha) + batchDensity * alpha;
|
|
698
|
+
} else {
|
|
699
|
+
tmp = batchDensity;
|
|
700
|
+
}
|
|
701
|
+
cs.chainDensity = tmp;
|
|
607
702
|
}
|
|
608
703
|
}
|
|
609
704
|
cs.committedProgressBlockNumber = chainAfterBatch.progressBlockNumber;
|
|
705
|
+
cs.processingBlockNumber = Primitive_int.max(cs.processingBlockNumber, chainAfterBatch.progressBlockNumber);
|
|
610
706
|
cs.numEventsProcessed = chainAfterBatch.totalEventsProcessed;
|
|
611
707
|
cs.transactionStore.prune(chainAfterBatch.progressBlockNumber);
|
|
612
708
|
cs.blockStore.prune(chainAfterBatch.progressBlockNumber);
|
|
@@ -634,6 +730,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
|
|
|
634
730
|
cs.transactionStore.rollback(rollbackTargetBlockNumber);
|
|
635
731
|
cs.blockStore.rollback(rollbackTargetBlockNumber);
|
|
636
732
|
cs.committedProgressBlockNumber = Primitive_int.min(cs.committedProgressBlockNumber, rollbackTargetBlockNumber);
|
|
733
|
+
cs.processingBlockNumber = Primitive_int.min(cs.processingBlockNumber, rollbackTargetBlockNumber);
|
|
637
734
|
return;
|
|
638
735
|
} else {
|
|
639
736
|
return;
|
|
@@ -657,6 +754,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
|
|
|
657
754
|
cs.transactionStore.rollback(newProgressBlockNumber);
|
|
658
755
|
cs.blockStore.rollback(newProgressBlockNumber);
|
|
659
756
|
cs.committedProgressBlockNumber = newProgressBlockNumber;
|
|
757
|
+
cs.processingBlockNumber = newProgressBlockNumber;
|
|
660
758
|
cs.numEventsProcessed = newTotalEventsProcessed;
|
|
661
759
|
}
|
|
662
760
|
|
|
@@ -682,8 +780,12 @@ export {
|
|
|
682
780
|
bufferReadyCount,
|
|
683
781
|
getProgressPercentage,
|
|
684
782
|
chainDensity,
|
|
783
|
+
effectiveDensity,
|
|
685
784
|
hasReadyItem,
|
|
686
785
|
isReadyToEnterReorgThreshold,
|
|
786
|
+
targetBlock,
|
|
787
|
+
blockAtProgress,
|
|
788
|
+
frontierProgress,
|
|
687
789
|
getNextQuery,
|
|
688
790
|
dispatch,
|
|
689
791
|
toChainData,
|
|
@@ -696,6 +798,7 @@ export {
|
|
|
696
798
|
isReady,
|
|
697
799
|
isFetchingAtHead,
|
|
698
800
|
isAtHeadWithoutEndBlock,
|
|
801
|
+
filterByClientAddress,
|
|
699
802
|
handleQueryResult,
|
|
700
803
|
materializeBatchItems,
|
|
701
804
|
materializePageItems,
|