envio 3.15.0 → 3.16.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/README.md +40 -34
- package/evm.schema.json +11 -2
- package/fuel.schema.json +10 -1
- package/index.d.ts +6 -0
- package/licenses/README.md +1 -1
- package/package.json +8 -8
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/ChainState.res +48 -7
- package/src/ChainState.res.mjs +27 -11
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +10 -3
- package/src/Config.res.mjs +4 -2
- package/src/Core.res +4 -40
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/FetchState.res +157 -69
- package/src/FetchState.res.mjs +144 -49
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +0 -49
- package/src/Internal.res.mjs +1 -80
- package/src/LoadLayer.res +14 -8
- package/src/LoadLayer.res.mjs +8 -6
- package/src/Main.res.mjs +1 -1
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +277 -948
- package/src/Storage.res.mjs +215 -707
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/Utils.res +0 -6
- package/src/Utils.res.mjs +0 -5
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +107 -174
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +3 -0
- package/src/sources/EvmChain.res.mjs +4 -2
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +84 -77
- package/src/sources/SourceManager.res.mjs +17 -20
- package/src/sources/SourceManager.resi +3 -4
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +11 -2
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -67
package/src/FetchState.res
CHANGED
|
@@ -864,6 +864,17 @@ module OptimizedPartitions = {
|
|
|
864
864
|
}
|
|
865
865
|
}
|
|
866
866
|
|
|
867
|
+
// When a contract's addresses leave the server-side filter. A switched contract
|
|
868
|
+
// is fetched by the single address-free partition and gated against the address
|
|
869
|
+
// store on our side. The switch is sticky for the run.
|
|
870
|
+
type clientFilterPolicy = {
|
|
871
|
+
// Past this many registered addresses. None never switches on count alone.
|
|
872
|
+
addressThreshold: option<int>,
|
|
873
|
+
// Every dynamic contract, whatever its address count. Keeps a chain at one
|
|
874
|
+
// query per block, of one shape, however many contracts it registers.
|
|
875
|
+
allDynamicContracts: bool,
|
|
876
|
+
}
|
|
877
|
+
|
|
867
878
|
type t = {
|
|
868
879
|
optimizedPartitions: OptimizedPartitions.t,
|
|
869
880
|
startBlock: int,
|
|
@@ -879,6 +890,7 @@ type t = {
|
|
|
879
890
|
// How much blocks behind the head we should query
|
|
880
891
|
// Needed to query before entering reorg threshold
|
|
881
892
|
blockLag: int,
|
|
893
|
+
blockThrottle: int,
|
|
882
894
|
// Buffer of items ordered from earliest to latest
|
|
883
895
|
buffer: array<Internal.item>,
|
|
884
896
|
// Caps how far ahead onBlock items are pre-generated (set to 2x the batch
|
|
@@ -890,10 +902,7 @@ type t = {
|
|
|
890
902
|
onBlockRegistrations: array<Internal.onBlockRegistration>,
|
|
891
903
|
knownHeight: int,
|
|
892
904
|
firstEventBlock: option<int>,
|
|
893
|
-
|
|
894
|
-
// switched to client-side filtering. None disables the switch, leaving every
|
|
895
|
-
// contract filtered server-side.
|
|
896
|
-
clientFilterAddressThreshold: option<int>,
|
|
905
|
+
clientFilterPolicy: clientFilterPolicy,
|
|
897
906
|
}
|
|
898
907
|
|
|
899
908
|
// The latest block whose items are all in the buffer: the lowest partition
|
|
@@ -1197,6 +1206,7 @@ let updateInternal = (
|
|
|
1197
1206
|
optimizedPartitions,
|
|
1198
1207
|
latestOnBlockBlockNumber,
|
|
1199
1208
|
blockLag,
|
|
1209
|
+
blockThrottle: fetchState.blockThrottle,
|
|
1200
1210
|
knownHeight,
|
|
1201
1211
|
// Single merge point: fold any onBlock items into the sorted base buffer.
|
|
1202
1212
|
buffer: switch blockItems {
|
|
@@ -1204,7 +1214,7 @@ let updateInternal = (
|
|
|
1204
1214
|
| blockItems => base->mergeIntoBuffer(blockItems)
|
|
1205
1215
|
},
|
|
1206
1216
|
firstEventBlock: fetchState.firstEventBlock,
|
|
1207
|
-
|
|
1217
|
+
clientFilterPolicy: fetchState.clientFilterPolicy,
|
|
1208
1218
|
}
|
|
1209
1219
|
|
|
1210
1220
|
updatedFetchState
|
|
@@ -1232,22 +1242,40 @@ type notice =
|
|
|
1232
1242
|
requestedFromBlock: int,
|
|
1233
1243
|
})
|
|
1234
1244
|
|
|
1235
|
-
//
|
|
1236
|
-
|
|
1245
|
+
// The client-filtered set once `policy` has judged `contractNames`. A copy, so
|
|
1246
|
+
// older fetch state snapshots keep theirs: Utils.Set.add mutates in place.
|
|
1247
|
+
let switchToClientSideFiltering = (
|
|
1237
1248
|
clientFilteredContracts: Utils.Set.t<string>,
|
|
1238
|
-
~
|
|
1249
|
+
~contractNames: array<string>,
|
|
1250
|
+
~policy: clientFilterPolicy,
|
|
1251
|
+
~dynamicContracts: Utils.Set.t<string>,
|
|
1252
|
+
~addressStore: AddressStore.t,
|
|
1239
1253
|
~onNotice,
|
|
1240
|
-
~addressCount,
|
|
1241
|
-
~threshold,
|
|
1242
1254
|
// A resumed fetch state re-derives the switch from the persisted addresses,
|
|
1243
|
-
// but it already happened - and was reported - in
|
|
1244
|
-
// threshold.
|
|
1255
|
+
// but it already happened - and was reported - in an earlier run.
|
|
1245
1256
|
~isAlreadyReported=false,
|
|
1246
1257
|
) => {
|
|
1247
|
-
clientFilteredContracts->Utils.Set.
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1258
|
+
let switched = clientFilteredContracts->Utils.Set.toArray->Utils.Set.fromArray
|
|
1259
|
+
contractNames->Array.forEach(contractName =>
|
|
1260
|
+
if !(switched->Utils.Set.has(contractName)) {
|
|
1261
|
+
if policy.allDynamicContracts && dynamicContracts->Utils.Set.has(contractName) {
|
|
1262
|
+
switched->Utils.Set.add(contractName)->ignore
|
|
1263
|
+
} else {
|
|
1264
|
+
switch policy.addressThreshold {
|
|
1265
|
+
| Some(threshold) =>
|
|
1266
|
+
let addressCount = addressStore->AddressStore.contractCount(contractName)
|
|
1267
|
+
if addressCount > threshold {
|
|
1268
|
+
switched->Utils.Set.add(contractName)->ignore
|
|
1269
|
+
if !isAlreadyReported {
|
|
1270
|
+
onNotice(SwitchedToClientSideFiltering({contractName, addressCount, threshold}))
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
| None => ()
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
)
|
|
1278
|
+
switched
|
|
1251
1279
|
}
|
|
1252
1280
|
|
|
1253
1281
|
// The block a partition will have fetched to once everything on its pending
|
|
@@ -1862,34 +1890,16 @@ let registerDynamicContracts = (
|
|
|
1862
1890
|
}
|
|
1863
1891
|
}
|
|
1864
1892
|
|
|
1865
|
-
//
|
|
1866
|
-
//
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
->Utils.Set.toArray
|
|
1876
|
-
->Utils.Set.fromArray
|
|
1877
|
-
dynamicContractsRef.contents
|
|
1878
|
-
->Utils.Set.toArray
|
|
1879
|
-
->Array.forEach(contractName => {
|
|
1880
|
-
let addressCount = addressStore->AddressStore.contractCount(contractName)
|
|
1881
|
-
if !(clientFilteredContracts->Utils.Set.has(contractName)) && addressCount > threshold {
|
|
1882
|
-
clientFilteredContracts->addClientFilteredContract(
|
|
1883
|
-
~contractName,
|
|
1884
|
-
~onNotice,
|
|
1885
|
-
~addressCount,
|
|
1886
|
-
~threshold,
|
|
1887
|
-
)
|
|
1888
|
-
}
|
|
1889
|
-
})
|
|
1890
|
-
clientFilteredContracts
|
|
1891
|
-
| None => fetchState.optimizedPartitions.clientFilteredContracts
|
|
1892
|
-
}
|
|
1893
|
+
// Collapse in createPartitions folds a switched contract's partitions
|
|
1894
|
+
// into the single address-free partition.
|
|
1895
|
+
let clientFilteredContracts =
|
|
1896
|
+
fetchState.optimizedPartitions.clientFilteredContracts->switchToClientSideFiltering(
|
|
1897
|
+
~contractNames=dynamicContractsRef.contents->Utils.Set.toArray,
|
|
1898
|
+
~policy=fetchState.clientFilterPolicy,
|
|
1899
|
+
~dynamicContracts=dynamicContractsRef.contents,
|
|
1900
|
+
~addressStore,
|
|
1901
|
+
~onNotice,
|
|
1902
|
+
)
|
|
1893
1903
|
|
|
1894
1904
|
// Only this batch's additions need partitions; everything already
|
|
1895
1905
|
// registered has one.
|
|
@@ -1920,6 +1930,48 @@ let registerDynamicContracts = (
|
|
|
1920
1930
|
}
|
|
1921
1931
|
}
|
|
1922
1932
|
|
|
1933
|
+
// Every dynamic contract, the ones registered from now on included, is fetched
|
|
1934
|
+
// address-free and filtered on our side. Its partitions fold into the single
|
|
1935
|
+
// address-free partition through the same collapse the address threshold uses.
|
|
1936
|
+
let switchDynamicContractsToClientSideFiltering = (fetchState: t, ~addressStore: AddressStore.t) =>
|
|
1937
|
+
if fetchState.clientFilterPolicy.allDynamicContracts {
|
|
1938
|
+
fetchState
|
|
1939
|
+
} else {
|
|
1940
|
+
let fetchState = {
|
|
1941
|
+
...fetchState,
|
|
1942
|
+
clientFilterPolicy: {...fetchState.clientFilterPolicy, allDynamicContracts: true},
|
|
1943
|
+
}
|
|
1944
|
+
let {
|
|
1945
|
+
dynamicContracts,
|
|
1946
|
+
clientFilteredContracts,
|
|
1947
|
+
maxAddrInPartition,
|
|
1948
|
+
nextPartitionIndex,
|
|
1949
|
+
} = fetchState.optimizedPartitions
|
|
1950
|
+
let switched =
|
|
1951
|
+
clientFilteredContracts
|
|
1952
|
+
->Utils.Set.toArray
|
|
1953
|
+
->Array.concat(dynamicContracts->Utils.Set.toArray)
|
|
1954
|
+
->Utils.Set.fromArray
|
|
1955
|
+
if switched->Utils.Set.size === clientFilteredContracts->Utils.Set.size {
|
|
1956
|
+
fetchState
|
|
1957
|
+
} else {
|
|
1958
|
+
fetchState->updateInternal(
|
|
1959
|
+
~optimizedPartitions=createPartitions(
|
|
1960
|
+
~registeringSetsByContract=Dict.make(),
|
|
1961
|
+
~addressStore,
|
|
1962
|
+
~dynamicContracts,
|
|
1963
|
+
~clientFilteredContracts=switched,
|
|
1964
|
+
~normalSelection=fetchState.normalSelection,
|
|
1965
|
+
~maxAddrInPartition,
|
|
1966
|
+
~nextPartitionIndex,
|
|
1967
|
+
~existingPartitions=fetchState.optimizedPartitions.entities->Dict.valuesToArray,
|
|
1968
|
+
~progressBlockNumber=0,
|
|
1969
|
+
~knownHeight=fetchState.knownHeight,
|
|
1970
|
+
),
|
|
1971
|
+
)
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1923
1975
|
/*
|
|
1924
1976
|
Updates fetchState with a response for a given query.
|
|
1925
1977
|
Throws if the partition with given query cannot be found (unexpected)
|
|
@@ -2387,6 +2439,20 @@ let acceptCandidates = (
|
|
|
2387
2439
|
}
|
|
2388
2440
|
}
|
|
2389
2441
|
|
|
2442
|
+
// A throttled chain lets `blockThrottle - 1` new blocks build up before it
|
|
2443
|
+
// fetches them, so a frontier that far behind the lagged head is waiting, not
|
|
2444
|
+
// behind. An end block the head has reached is fetched without waiting.
|
|
2445
|
+
let blocksBehindHeadAllowedByThrottle = ({blockThrottle, endBlock, knownHeight, blockLag}: t) =>
|
|
2446
|
+
switch endBlock {
|
|
2447
|
+
| Some(endBlock) if knownHeight - blockLag >= endBlock => 0
|
|
2448
|
+
| _ => Pervasives.max(0, blockThrottle - 1)
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
// The highest block the chain fetches up to right now: the lagged head, less the
|
|
2452
|
+
// blocks a throttled chain lets build up first.
|
|
2453
|
+
let headFetchTarget = ({knownHeight, blockLag} as fetchState: t) =>
|
|
2454
|
+
knownHeight - blockLag - fetchState->blocksBehindHeadAllowedByThrottle
|
|
2455
|
+
|
|
2390
2456
|
// Candidate queries are sized against chainTargetBlock, the soft querying
|
|
2391
2457
|
// horizon the owning chain wants to reach this tick — derived by ChainState
|
|
2392
2458
|
// from its share of the indexer-wide buffer budget and its chain-level event
|
|
@@ -2415,7 +2481,7 @@ let acceptCandidates = (
|
|
|
2415
2481
|
// rangeTargetDensity × (chainTargetBlock − fromBlock + 1) / inRangeCount — so
|
|
2416
2482
|
// unknown-density partitions probe in parallel within one budget.
|
|
2417
2483
|
let getNextQuery = (
|
|
2418
|
-
{optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight, endBlock}: t,
|
|
2484
|
+
{optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight, endBlock} as fetchState: t,
|
|
2419
2485
|
~chainTargetBlock: int,
|
|
2420
2486
|
~chainTargetItems: float,
|
|
2421
2487
|
) => {
|
|
@@ -2423,7 +2489,8 @@ let getNextQuery = (
|
|
|
2423
2489
|
if headBlockNumber <= 0 {
|
|
2424
2490
|
WaitingForNewBlock
|
|
2425
2491
|
} else {
|
|
2426
|
-
let
|
|
2492
|
+
let caughtUpBlockNumber = headBlockNumber - fetchState->blocksBehindHeadAllowedByThrottle
|
|
2493
|
+
let isOnBlockBehindTheHead = latestOnBlockBlockNumber < caughtUpBlockNumber
|
|
2427
2494
|
let shouldWaitForNewBlock = ref(
|
|
2428
2495
|
switch endBlock {
|
|
2429
2496
|
| Some(endBlock) => headBlockNumber < endBlock
|
|
@@ -2468,7 +2535,7 @@ let getNextQuery = (
|
|
|
2468
2535
|
}
|
|
2469
2536
|
}
|
|
2470
2537
|
inFlightCounts->Array.setUnsafe(idx, inFlightCount.contents)
|
|
2471
|
-
if p.mutPendingQueries->Array.length > 0 || p.latestFetchedBlock <
|
|
2538
|
+
if p.mutPendingQueries->Array.length > 0 || p.latestFetchedBlock < caughtUpBlockNumber {
|
|
2472
2539
|
// Even if there are some partitions waiting for the new block
|
|
2473
2540
|
// We still want to wait for all partitions reaching the head
|
|
2474
2541
|
// because they might update knownHeight in their response
|
|
@@ -2647,6 +2714,7 @@ let make = (
|
|
|
2647
2714
|
~progressBlockNumber=startBlock - 1,
|
|
2648
2715
|
~onBlockRegistrations=[],
|
|
2649
2716
|
~blockLag=0,
|
|
2717
|
+
~blockThrottle=0,
|
|
2650
2718
|
~firstEventBlock=None,
|
|
2651
2719
|
~clientFilterAddressThreshold=None,
|
|
2652
2720
|
~isResumed=false,
|
|
@@ -2729,7 +2797,6 @@ let make = (
|
|
|
2729
2797
|
})
|
|
2730
2798
|
|
|
2731
2799
|
let dynamicContracts = Utils.Set.make()
|
|
2732
|
-
let clientFilteredContracts = Utils.Set.make()
|
|
2733
2800
|
let registeringSetsByContract = Dict.make()
|
|
2734
2801
|
|
|
2735
2802
|
// What each contract needs a partition for is read back off the store rather
|
|
@@ -2753,26 +2820,24 @@ let make = (
|
|
|
2753
2820
|
}
|
|
2754
2821
|
})
|
|
2755
2822
|
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
switch clientFilterAddressThreshold {
|
|
2760
|
-
| Some(threshold) =>
|
|
2761
|
-
registeringSetsByContract->Utils.Dict.forEachWithKey((set, contractName) => {
|
|
2762
|
-
let addressCount = set->AddressSet.size
|
|
2763
|
-
if addressCount > threshold {
|
|
2764
|
-
clientFilteredContracts->addClientFilteredContract(
|
|
2765
|
-
~contractName,
|
|
2766
|
-
~onNotice,
|
|
2767
|
-
~addressCount,
|
|
2768
|
-
~threshold,
|
|
2769
|
-
~isAlreadyReported=isResumed,
|
|
2770
|
-
)
|
|
2771
|
-
}
|
|
2772
|
-
})
|
|
2773
|
-
| None => ()
|
|
2823
|
+
let clientFilterPolicy = {
|
|
2824
|
+
addressThreshold: clientFilterAddressThreshold,
|
|
2825
|
+
allDynamicContracts: false,
|
|
2774
2826
|
}
|
|
2775
2827
|
|
|
2828
|
+
// Switch at creation whatever the threshold already covers: a config
|
|
2829
|
+
// contract with a large static address list, or a dynamic contract restored
|
|
2830
|
+
// from a large persisted set.
|
|
2831
|
+
let clientFilteredContracts =
|
|
2832
|
+
Utils.Set.make()->switchToClientSideFiltering(
|
|
2833
|
+
~contractNames=registeringSetsByContract->Dict.keysToArray,
|
|
2834
|
+
~policy=clientFilterPolicy,
|
|
2835
|
+
~dynamicContracts,
|
|
2836
|
+
~addressStore,
|
|
2837
|
+
~onNotice,
|
|
2838
|
+
~isAlreadyReported=isResumed,
|
|
2839
|
+
)
|
|
2840
|
+
|
|
2776
2841
|
let optimizedPartitions = createPartitions(
|
|
2777
2842
|
~registeringSetsByContract,
|
|
2778
2843
|
~addressStore,
|
|
@@ -2836,12 +2901,13 @@ let make = (
|
|
|
2836
2901
|
latestOnBlockBlockNumber,
|
|
2837
2902
|
normalSelection,
|
|
2838
2903
|
blockLag,
|
|
2904
|
+
blockThrottle,
|
|
2839
2905
|
onBlockRegistrations,
|
|
2840
2906
|
maxOnBlockBufferSize,
|
|
2841
2907
|
knownHeight,
|
|
2842
2908
|
buffer,
|
|
2843
2909
|
firstEventBlock,
|
|
2844
|
-
|
|
2910
|
+
clientFilterPolicy,
|
|
2845
2911
|
}
|
|
2846
2912
|
|
|
2847
2913
|
fetchState
|
|
@@ -3054,15 +3120,37 @@ let isActivelyIndexing = ({endBlock} as fetchState: t) => {
|
|
|
3054
3120
|
// True once the fetch frontier has reached the (lagged) head or endBlock,
|
|
3055
3121
|
// regardless of whether the buffer has been consumed yet. Unlike
|
|
3056
3122
|
// isReadyToEnterReorgThreshold, fetched-but-unprocessed items still count.
|
|
3057
|
-
let isFetchingAtHead = ({endBlock,
|
|
3123
|
+
let isFetchingAtHead = ({endBlock, knownHeight} as fetchState: t) => {
|
|
3058
3124
|
let bufferBlockNumber = fetchState->bufferBlockNumber
|
|
3059
3125
|
knownHeight !== 0 &&
|
|
3060
3126
|
switch endBlock {
|
|
3061
3127
|
| Some(endBlock) if bufferBlockNumber >= endBlock => true
|
|
3062
|
-
| _ => bufferBlockNumber >=
|
|
3128
|
+
| _ => bufferBlockNumber >= fetchState->headFetchTarget
|
|
3063
3129
|
}
|
|
3064
3130
|
}
|
|
3065
3131
|
|
|
3132
|
+
// Counted in blocks whatever the chain's block time: the chain still fetches
|
|
3133
|
+
// block by block near the head, and an address-free query must never reach back
|
|
3134
|
+
// into a range a partition is still backfilling.
|
|
3135
|
+
let headClientFilteringDistance = 200
|
|
3136
|
+
|
|
3137
|
+
// Every partition is within `headClientFilteringDistance` of the fetch target. A
|
|
3138
|
+
// chain with no head to follow never is: no known height yet, or an end block it
|
|
3139
|
+
// stops at before the head.
|
|
3140
|
+
let isWithinHeadClientFilteringDistance = (
|
|
3141
|
+
{endBlock, blockLag, knownHeight, optimizedPartitions} as fetchState: t,
|
|
3142
|
+
) =>
|
|
3143
|
+
knownHeight !== 0 &&
|
|
3144
|
+
switch endBlock {
|
|
3145
|
+
| Some(endBlock) => endBlock > knownHeight - blockLag
|
|
3146
|
+
| None => true
|
|
3147
|
+
} &&
|
|
3148
|
+
switch optimizedPartitions->OptimizedPartitions.getLatestFullyFetchedBlock {
|
|
3149
|
+
| Some(latestFetchedBlock) =>
|
|
3150
|
+
fetchState->headFetchTarget - latestFetchedBlock <= headClientFilteringDistance
|
|
3151
|
+
| None => true
|
|
3152
|
+
}
|
|
3153
|
+
|
|
3066
3154
|
// Frontier at (or within `tolerance` of) the lagged head with no processable
|
|
3067
3155
|
// items left — the moment the chain can cross into the reorg threshold.
|
|
3068
3156
|
// `tolerance` absorbs the head advancing between a chain catching up and this
|