envio 3.15.0-subgraph → 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 +3 -3
- package/fuel.schema.json +2 -2
- package/index.d.ts +3 -3
- package/licenses/README.md +1 -1
- package/package.json +9 -10
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +0 -7
- package/src/Bin.res.mjs +0 -8
- package/src/ChainFetching.res +17 -456
- package/src/ChainFetching.res.mjs +33 -404
- package/src/ChainState.res +48 -83
- package/src/ChainState.res.mjs +83 -115
- package/src/ChainState.resi +0 -26
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +7 -16
- package/src/Config.res.mjs +4 -11
- package/src/ContractRegisterContext.res +6 -3
- package/src/ContractRegisterContext.res.mjs +2 -4
- package/src/Core.res +5 -136
- package/src/Core.res.mjs +1 -90
- package/src/CrossChainState.res +2 -8
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +4 -7
- package/src/Ecosystem.res.mjs +8 -8
- 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/Env.res +0 -16
- package/src/Env.res.mjs +0 -11
- package/src/EventProcessing.res +1 -38
- package/src/EventProcessing.res.mjs +1 -28
- package/src/FetchState.res +160 -319
- package/src/FetchState.res.mjs +182 -292
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +15 -39
- package/src/HandlerLoader.res.mjs +8 -27
- package/src/HandlerRegister.res +0 -4
- package/src/HandlerRegister.res.mjs +2 -5
- package/src/HandlerRegister.resi +0 -2
- 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 -110
- package/src/Internal.res.mjs +1 -115
- package/src/LoadLayer.res +21 -47
- package/src/LoadLayer.res.mjs +47 -72
- package/src/LoadLayer.resi +0 -26
- package/src/Main.res +1 -14
- package/src/Main.res.mjs +3 -4
- 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/RunScope.res +0 -3
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +26 -42
- package/src/SimulateItems.res.mjs +16 -40
- 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 -998
- package/src/Storage.res.mjs +216 -731
- 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/UserContext.res +46 -410
- package/src/UserContext.res.mjs +30 -318
- package/src/Utils.res +0 -23
- package/src/Utils.res.mjs +1 -17
- 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 -175
- 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/AddressSet.res +0 -2
- package/src/sources/AddressStore.res +0 -3
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -7
- package/src/sources/EvmChain.res.mjs +5 -4
- 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/HyperSync.res +1 -2
- package/src/sources/HyperSync.res.mjs +1 -2
- 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 +85 -104
- package/src/sources/SourceManager.res.mjs +18 -37
- package/src/sources/SourceManager.resi +3 -5
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +4 -3
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +3 -3
- package/src/EffectCacheLookup.res +0 -98
- package/src/EffectCacheLookup.res.mjs +0 -116
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/PreloadLookahead.res +0 -184
- package/src/PreloadLookahead.res.mjs +0 -197
- package/src/SubgraphLog.res +0 -19
- package/src/SubgraphLog.res.mjs +0 -26
- package/src/SyncWrites.res +0 -101
- package/src/SyncWrites.res.mjs +0 -98
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -60
- package/src/sources/CallSource.res +0 -274
- package/src/sources/CallSource.res.mjs +0 -196
- package/src/subgraph/abi-types.ts +0 -84
- package/src/subgraph/aggregations.ts +0 -745
- package/src/subgraph/as-package.ts +0 -143
- package/src/subgraph/assemblyscript-regex.ts +0 -67
- package/src/subgraph/assemblyscript.ts +0 -731
- package/src/subgraph/blocks.ts +0 -398
- package/src/subgraph/calls-source.ts +0 -702
- package/src/subgraph/calls.ts +0 -258
- package/src/subgraph/conformance.ts +0 -106
- package/src/subgraph/errors.ts +0 -85
- package/src/subgraph/graft.ts +0 -73
- package/src/subgraph/graph-cli-worker.mjs +0 -35
- package/src/subgraph/graph-cli.ts +0 -900
- package/src/subgraph/graph-node-decimal.ts +0 -199
- package/src/subgraph/graph-ts-enums.ts +0 -28
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -4280
- package/src/subgraph/hosts.ts +0 -554
- package/src/subgraph/log.ts +0 -28
- package/src/subgraph/receipts.ts +0 -184
- package/src/subgraph/register-slots.ts +0 -93
- package/src/subgraph/rollup.ts +0 -109
- package/src/subgraph/rpc.ts +0 -337
- package/src/subgraph/runtime.ts +0 -2060
- package/src/subgraph/scope.ts +0 -177
- package/src/subgraph/stats.ts +0 -42
- package/src/subgraph/template-instances.ts +0 -66
- package/src/subgraph/toolchain.ts +0 -327
- package/src/subgraph/transient.ts +0 -176
package/src/FetchState.res
CHANGED
|
@@ -864,10 +864,16 @@ module OptimizedPartitions = {
|
|
|
864
864
|
}
|
|
865
865
|
}
|
|
866
866
|
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
type
|
|
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
|
+
}
|
|
871
877
|
|
|
872
878
|
type t = {
|
|
873
879
|
optimizedPartitions: OptimizedPartitions.t,
|
|
@@ -884,6 +890,7 @@ type t = {
|
|
|
884
890
|
// How much blocks behind the head we should query
|
|
885
891
|
// Needed to query before entering reorg threshold
|
|
886
892
|
blockLag: int,
|
|
893
|
+
blockThrottle: int,
|
|
887
894
|
// Buffer of items ordered from earliest to latest
|
|
888
895
|
buffer: array<Internal.item>,
|
|
889
896
|
// Caps how far ahead onBlock items are pre-generated (set to 2x the batch
|
|
@@ -895,20 +902,7 @@ type t = {
|
|
|
895
902
|
onBlockRegistrations: array<Internal.onBlockRegistration>,
|
|
896
903
|
knownHeight: int,
|
|
897
904
|
firstEventBlock: option<int>,
|
|
898
|
-
|
|
899
|
-
// switched to client-side filtering. None disables the switch, leaving every
|
|
900
|
-
// contract filtered server-side.
|
|
901
|
-
clientFilterAddressThreshold: option<int>,
|
|
902
|
-
// Subgraph mode only: the block each dynamically registered address was
|
|
903
|
-
// registered in, keyed by contract and lowercase address, until fetching
|
|
904
|
-
// passes it. Its events in that block run after the rest of the block, as
|
|
905
|
-
// graph-node runs a new data source's creation-block triggers.
|
|
906
|
-
creationBlocks?: dict<creationBlock>,
|
|
907
|
-
// Set when an onBlock registration has a contractRegister: the last block
|
|
908
|
-
// whose block-handler register passes have run and whose registrations are
|
|
909
|
-
// applied. No block item past it is generated, so none is processed before
|
|
910
|
-
// the data sources its block created are fetched.
|
|
911
|
-
blockRegisterThrough?: int,
|
|
905
|
+
clientFilterPolicy: clientFilterPolicy,
|
|
912
906
|
}
|
|
913
907
|
|
|
914
908
|
// The latest block whose items are all in the buffer: the lowest partition
|
|
@@ -998,65 +992,6 @@ let compareTiebreak = (a: Internal.item, b: Internal.item): int => {
|
|
|
998
992
|
}
|
|
999
993
|
}
|
|
1000
994
|
|
|
1001
|
-
// Within a block, graph-node runs a subgraph's triggers in this order: logs and
|
|
1002
|
-
// calls by transaction — a transaction's logs, then its calls in trace order —
|
|
1003
|
-
// then the block triggers of `filter: call` handlers, one per call, then the
|
|
1004
|
-
// block handlers. A call item is told apart by its rank (see
|
|
1005
|
-
// `Internal.getItemCallRank`), and only a run that has one pays for this
|
|
1006
|
-
// comparison. Creation-block items (rank 4) keep their place after everything
|
|
1007
|
-
// else, ordered among themselves by the same transaction rule. A `once`
|
|
1008
|
-
// handler's item (rank -1) comes before all of them.
|
|
1009
|
-
let blockOrderRank = (item: Internal.item) =>
|
|
1010
|
-
switch item->Internal.getItemCreationRound {
|
|
1011
|
-
| Some(round) => 3 + round
|
|
1012
|
-
| None =>
|
|
1013
|
-
if item->Internal.getItemKind !== 0 {
|
|
1014
|
-
item->Internal.itemRunsFirst ? -1 : 3
|
|
1015
|
-
} else if item->Internal.getItemCallRank === Some(2) {
|
|
1016
|
-
2
|
|
1017
|
-
} else {
|
|
1018
|
-
0
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
let compareWithCalls = (a: Internal.item, b: Internal.item): int => {
|
|
1023
|
-
let ra = blockOrderRank(a)
|
|
1024
|
-
let rb = blockOrderRank(b)
|
|
1025
|
-
if ra !== rb {
|
|
1026
|
-
ra < rb ? -1 : 1
|
|
1027
|
-
} else if ra === 3 || ra === -1 {
|
|
1028
|
-
// Block handlers: as before.
|
|
1029
|
-
let la = a->Internal.getItemLogIndex
|
|
1030
|
-
let lb = b->Internal.getItemLogIndex
|
|
1031
|
-
if la != lb {
|
|
1032
|
-
la < lb ? -1 : 1
|
|
1033
|
-
} else {
|
|
1034
|
-
compareTiebreak(a, b)
|
|
1035
|
-
}
|
|
1036
|
-
} else {
|
|
1037
|
-
let ta = a->Internal.getItemTransactionIndex
|
|
1038
|
-
let tb = b->Internal.getItemTransactionIndex
|
|
1039
|
-
if ta != tb {
|
|
1040
|
-
ta < tb ? -1 : 1
|
|
1041
|
-
} else {
|
|
1042
|
-
// A transaction's logs precede its calls.
|
|
1043
|
-
let ca = a->Internal.getItemCallRank->Option.isSome ? 1 : 0
|
|
1044
|
-
let cb = b->Internal.getItemCallRank->Option.isSome ? 1 : 0
|
|
1045
|
-
if ca !== cb {
|
|
1046
|
-
ca < cb ? -1 : 1
|
|
1047
|
-
} else {
|
|
1048
|
-
let la = a->Internal.getItemLogIndex
|
|
1049
|
-
let lb = b->Internal.getItemLogIndex
|
|
1050
|
-
if la != lb {
|
|
1051
|
-
la < lb ? -1 : 1
|
|
1052
|
-
} else {
|
|
1053
|
-
compareTiebreak(a, b)
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
995
|
// Total order on buffer items: block, then item kind, then the ecosystem's
|
|
1061
996
|
// within-block order, then registration index. Returns a plain int (-1/0/1)
|
|
1062
997
|
// with explicit field comparisons so it can be called directly from the
|
|
@@ -1068,32 +1003,15 @@ let compareWithCalls = (a: Internal.item, b: Internal.item): int => {
|
|
|
1068
1003
|
// block's handlers by construction. A sentinel log index for block items
|
|
1069
1004
|
// would put the same guarantee at the mercy of how large an ecosystem's key
|
|
1070
1005
|
// grows — which is how SVM, keyed by transaction index, came to run slot
|
|
1071
|
-
// handlers ahead of most of a slot's instructions.
|
|
1072
|
-
// is the exception: it runs ahead of its block's events.
|
|
1006
|
+
// handlers ahead of most of a slot's instructions.
|
|
1073
1007
|
let compareBufferItem = (a: Internal.item, b: Internal.item): int => {
|
|
1074
1008
|
let ba = a->Internal.getItemBlockNumber
|
|
1075
1009
|
let bb = b->Internal.getItemBlockNumber
|
|
1076
1010
|
if ba != bb {
|
|
1077
1011
|
ba < bb ? -1 : 1
|
|
1078
|
-
} else if Internal.callOrderingActive.contents {
|
|
1079
|
-
compareWithCalls(a, b)
|
|
1080
1012
|
} else {
|
|
1081
|
-
let ka =
|
|
1082
|
-
|
|
1083
|
-
| None =>
|
|
1084
|
-
switch a->Internal.getItemKind {
|
|
1085
|
-
| 0 => 0
|
|
1086
|
-
| kind => a->Internal.itemRunsFirst ? -1 : kind
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
let kb = switch b->Internal.getItemCreationRound {
|
|
1090
|
-
| Some(round) => 1 + round
|
|
1091
|
-
| None =>
|
|
1092
|
-
switch b->Internal.getItemKind {
|
|
1093
|
-
| 0 => 0
|
|
1094
|
-
| kind => b->Internal.itemRunsFirst ? -1 : kind
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1013
|
+
let ka = a->Internal.getItemKind
|
|
1014
|
+
let kb = b->Internal.getItemKind
|
|
1097
1015
|
if ka !== kb {
|
|
1098
1016
|
ka < kb ? -1 : 1
|
|
1099
1017
|
} else {
|
|
@@ -1115,7 +1033,6 @@ let compareBufferItem = (a: Internal.item, b: Internal.item): int => {
|
|
|
1115
1033
|
let isSameLog = (a: Internal.item, b: Internal.item): bool =>
|
|
1116
1034
|
a->Internal.getItemKind === 0 &&
|
|
1117
1035
|
b->Internal.getItemKind === 0 &&
|
|
1118
|
-
a->Internal.getItemCallRank === b->Internal.getItemCallRank &&
|
|
1119
1036
|
a->Internal.getItemBlockNumber === b->Internal.getItemBlockNumber &&
|
|
1120
1037
|
a->Internal.getItemLogIndex === b->Internal.getItemLogIndex &&
|
|
1121
1038
|
switch (a->Internal.getItemOrderPath, b->Internal.getItemOrderPath) {
|
|
@@ -1269,10 +1186,6 @@ let updateInternal = (
|
|
|
1269
1186
|
},
|
|
1270
1187
|
knownHeight,
|
|
1271
1188
|
)
|
|
1272
|
-
let maxBlockNumber = switch fetchState.blockRegisterThrough {
|
|
1273
|
-
| Some(through) => Pervasives.min(maxBlockNumber, through)
|
|
1274
|
-
| None => maxBlockNumber
|
|
1275
|
-
}
|
|
1276
1189
|
appendOnBlockItems(
|
|
1277
1190
|
~mutItems=blockItems,
|
|
1278
1191
|
~onBlockRegistrations,
|
|
@@ -1293,6 +1206,7 @@ let updateInternal = (
|
|
|
1293
1206
|
optimizedPartitions,
|
|
1294
1207
|
latestOnBlockBlockNumber,
|
|
1295
1208
|
blockLag,
|
|
1209
|
+
blockThrottle: fetchState.blockThrottle,
|
|
1296
1210
|
knownHeight,
|
|
1297
1211
|
// Single merge point: fold any onBlock items into the sorted base buffer.
|
|
1298
1212
|
buffer: switch blockItems {
|
|
@@ -1300,9 +1214,7 @@ let updateInternal = (
|
|
|
1300
1214
|
| blockItems => base->mergeIntoBuffer(blockItems)
|
|
1301
1215
|
},
|
|
1302
1216
|
firstEventBlock: fetchState.firstEventBlock,
|
|
1303
|
-
|
|
1304
|
-
creationBlocks: ?fetchState.creationBlocks,
|
|
1305
|
-
blockRegisterThrough: ?fetchState.blockRegisterThrough,
|
|
1217
|
+
clientFilterPolicy: fetchState.clientFilterPolicy,
|
|
1306
1218
|
}
|
|
1307
1219
|
|
|
1308
1220
|
updatedFetchState
|
|
@@ -1330,22 +1242,40 @@ type notice =
|
|
|
1330
1242
|
requestedFromBlock: int,
|
|
1331
1243
|
})
|
|
1332
1244
|
|
|
1333
|
-
//
|
|
1334
|
-
|
|
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 = (
|
|
1335
1248
|
clientFilteredContracts: Utils.Set.t<string>,
|
|
1336
|
-
~
|
|
1249
|
+
~contractNames: array<string>,
|
|
1250
|
+
~policy: clientFilterPolicy,
|
|
1251
|
+
~dynamicContracts: Utils.Set.t<string>,
|
|
1252
|
+
~addressStore: AddressStore.t,
|
|
1337
1253
|
~onNotice,
|
|
1338
|
-
~addressCount,
|
|
1339
|
-
~threshold,
|
|
1340
1254
|
// A resumed fetch state re-derives the switch from the persisted addresses,
|
|
1341
|
-
// but it already happened - and was reported - in
|
|
1342
|
-
// threshold.
|
|
1255
|
+
// but it already happened - and was reported - in an earlier run.
|
|
1343
1256
|
~isAlreadyReported=false,
|
|
1344
1257
|
) => {
|
|
1345
|
-
clientFilteredContracts->Utils.Set.
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
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
|
|
1349
1279
|
}
|
|
1350
1280
|
|
|
1351
1281
|
// The block a partition will have fetched to once everything on its pending
|
|
@@ -1821,54 +1751,6 @@ OptimizedPartitions.t => {
|
|
|
1821
1751
|
)
|
|
1822
1752
|
}
|
|
1823
1753
|
|
|
1824
|
-
let creationBlockKey = (~contractName, ~address: Address.t) =>
|
|
1825
|
-
`${contractName}:${address->Address.toString->String.toLowerCase}`
|
|
1826
|
-
|
|
1827
|
-
// Marks the response's events that were logged in the block their address was
|
|
1828
|
-
// registered in, once the registrations fetching has already passed are
|
|
1829
|
-
// dropped: those can't receive another item.
|
|
1830
|
-
let markCreationBlockEvents = (creationBlocks: dict<creationBlock>, ~newItems, ~fetchedThrough) => {
|
|
1831
|
-
creationBlocks
|
|
1832
|
-
->Dict.toArray
|
|
1833
|
-
->Array.forEach(((key, {block})) =>
|
|
1834
|
-
if block < fetchedThrough {
|
|
1835
|
-
creationBlocks->Utils.Dict.deleteInPlace(key)
|
|
1836
|
-
}
|
|
1837
|
-
)
|
|
1838
|
-
newItems->Array.forEach(item =>
|
|
1839
|
-
if item->Internal.getItemKind === 0 {
|
|
1840
|
-
let eventItem = item->Internal.castUnsafeEventItem
|
|
1841
|
-
let key = creationBlockKey(
|
|
1842
|
-
~contractName=eventItem.onEventRegistration.eventConfig.contractName,
|
|
1843
|
-
~address=eventItem.payload->Internal.getPayloadSrcAddress,
|
|
1844
|
-
)
|
|
1845
|
-
switch creationBlocks->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
1846
|
-
| Some({block, round}) if block === eventItem.blockNumber =>
|
|
1847
|
-
item->Internal.markItemCreationRound(round)
|
|
1848
|
-
| _ => ()
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
)
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
// The round a registration made by `item`'s handler belongs to: one past the
|
|
1855
|
-
// round `item` itself runs in, which is its address's registration round when
|
|
1856
|
-
// the event was logged in the block that address was registered in.
|
|
1857
|
-
let creationRoundOfRegistration = (fetchState: t, ~item: Internal.item) =>
|
|
1858
|
-
switch fetchState.creationBlocks {
|
|
1859
|
-
| None => 1
|
|
1860
|
-
| Some(creationBlocks) =>
|
|
1861
|
-
let eventItem = item->Internal.castUnsafeEventItem
|
|
1862
|
-
let key = creationBlockKey(
|
|
1863
|
-
~contractName=eventItem.onEventRegistration.eventConfig.contractName,
|
|
1864
|
-
~address=eventItem.payload->Internal.getPayloadSrcAddress,
|
|
1865
|
-
)
|
|
1866
|
-
switch creationBlocks->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
1867
|
-
| Some({block, round}) if block === eventItem.blockNumber => round + 1
|
|
1868
|
-
| _ => 1
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
1754
|
let registerDynamicContracts = (
|
|
1873
1755
|
fetchState: t,
|
|
1874
1756
|
~addressStore: AddressStore.t,
|
|
@@ -1907,17 +1789,6 @@ let registerDynamicContracts = (
|
|
|
1907
1789
|
let verdict = verdicts->Array.getUnsafe(idx)
|
|
1908
1790
|
switch verdict {
|
|
1909
1791
|
| Added({fetchable: true}) =>
|
|
1910
|
-
switch fetchState.creationBlocks {
|
|
1911
|
-
| Some(creationBlocks) =>
|
|
1912
|
-
creationBlocks->Dict.set(
|
|
1913
|
-
creationBlockKey(~contractName=registration.contractName, ~address=registration.address),
|
|
1914
|
-
{
|
|
1915
|
-
block: registration.registrationBlock,
|
|
1916
|
-
round: registration.creationRound->Option.getOr(1),
|
|
1917
|
-
},
|
|
1918
|
-
)
|
|
1919
|
-
| None => ()
|
|
1920
|
-
}
|
|
1921
1792
|
if !(registeringContractNames->Array.includes(registration.contractName)) {
|
|
1922
1793
|
registeringContractNames->Array.push(registration.contractName)->ignore
|
|
1923
1794
|
}
|
|
@@ -2019,34 +1890,16 @@ let registerDynamicContracts = (
|
|
|
2019
1890
|
}
|
|
2020
1891
|
}
|
|
2021
1892
|
|
|
2022
|
-
//
|
|
2023
|
-
//
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
->Utils.Set.toArray
|
|
2033
|
-
->Utils.Set.fromArray
|
|
2034
|
-
dynamicContractsRef.contents
|
|
2035
|
-
->Utils.Set.toArray
|
|
2036
|
-
->Array.forEach(contractName => {
|
|
2037
|
-
let addressCount = addressStore->AddressStore.contractCount(contractName)
|
|
2038
|
-
if !(clientFilteredContracts->Utils.Set.has(contractName)) && addressCount > threshold {
|
|
2039
|
-
clientFilteredContracts->addClientFilteredContract(
|
|
2040
|
-
~contractName,
|
|
2041
|
-
~onNotice,
|
|
2042
|
-
~addressCount,
|
|
2043
|
-
~threshold,
|
|
2044
|
-
)
|
|
2045
|
-
}
|
|
2046
|
-
})
|
|
2047
|
-
clientFilteredContracts
|
|
2048
|
-
| None => fetchState.optimizedPartitions.clientFilteredContracts
|
|
2049
|
-
}
|
|
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
|
+
)
|
|
2050
1903
|
|
|
2051
1904
|
// Only this batch's additions need partitions; everything already
|
|
2052
1905
|
// registered has one.
|
|
@@ -2077,6 +1930,48 @@ let registerDynamicContracts = (
|
|
|
2077
1930
|
}
|
|
2078
1931
|
}
|
|
2079
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
|
+
|
|
2080
1975
|
/*
|
|
2081
1976
|
Updates fetchState with a response for a given query.
|
|
2082
1977
|
Throws if the partition with given query cannot be found (unexpected)
|
|
@@ -2098,80 +1993,12 @@ let handleQueryResult = (fetchState: t, ~query: query, ~latestFetchedBlock: int,
|
|
|
2098
1993
|
~mutItems=?{
|
|
2099
1994
|
switch newItems {
|
|
2100
1995
|
| [] => None
|
|
2101
|
-
| _ =>
|
|
2102
|
-
switch fetchState.creationBlocks {
|
|
2103
|
-
| Some(creationBlocks) =>
|
|
2104
|
-
creationBlocks->markCreationBlockEvents(
|
|
2105
|
-
~newItems,
|
|
2106
|
-
~fetchedThrough=fetchState->bufferBlockNumber,
|
|
2107
|
-
)
|
|
2108
|
-
| None => ()
|
|
2109
|
-
}
|
|
2110
|
-
Some(fetchState.buffer->mergeIntoBuffer(newItems))
|
|
1996
|
+
| _ => Some(fetchState.buffer->mergeIntoBuffer(newItems))
|
|
2111
1997
|
}
|
|
2112
1998
|
},
|
|
2113
1999
|
)
|
|
2114
2000
|
}
|
|
2115
2001
|
|
|
2116
|
-
// The items of the block handlers' register passes for the blocks after
|
|
2117
|
-
// `after`, through `through`, at most about `limit` of them in whole blocks;
|
|
2118
|
-
// and the last block they cover. `nextBlockRegisterItems` starts after the
|
|
2119
|
-
// last block passed.
|
|
2120
|
-
let capAtEndBlock = (fetchState: t, block) =>
|
|
2121
|
-
switch fetchState.endBlock {
|
|
2122
|
-
| Some(endBlock) => Pervasives.min(block, endBlock)
|
|
2123
|
-
| None => block
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
let canAdvanceBlockRegisters = (fetchState: t, ~through) =>
|
|
2127
|
-
switch fetchState.blockRegisterThrough {
|
|
2128
|
-
| Some(after) => fetchState->capAtEndBlock(through) > after
|
|
2129
|
-
| None => false
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
|
-
let blockRegisterItemsAfter = (fetchState: t, ~after, ~through, ~limit) =>
|
|
2133
|
-
switch fetchState.blockRegisterThrough {
|
|
2134
|
-
| Some(_) if fetchState->capAtEndBlock(through) > after =>
|
|
2135
|
-
let through = fetchState->capAtEndBlock(through)
|
|
2136
|
-
let items = []
|
|
2137
|
-
let covered = appendOnBlockItems(
|
|
2138
|
-
~mutItems=items,
|
|
2139
|
-
~onBlockRegistrations=fetchState.onBlockRegistrations->Array.filter((
|
|
2140
|
-
r: Internal.onBlockRegistration,
|
|
2141
|
-
) => r.contractRegister !== None),
|
|
2142
|
-
~indexerStartBlock=fetchState.startBlock,
|
|
2143
|
-
~fromBlock=after,
|
|
2144
|
-
~maxBlockNumber=through,
|
|
2145
|
-
~maxOnBlockBufferSize=limit,
|
|
2146
|
-
)
|
|
2147
|
-
Some((items, covered))
|
|
2148
|
-
| _ => None
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
let nextBlockRegisterItems = (fetchState: t, ~through, ~limit) =>
|
|
2152
|
-
switch fetchState.blockRegisterThrough {
|
|
2153
|
-
| Some(after) => fetchState->blockRegisterItemsAfter(~after, ~through, ~limit)
|
|
2154
|
-
| None => None
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
let setBlockRegisterThrough = (fetchState: t, ~through) =>
|
|
2158
|
-
switch fetchState.blockRegisterThrough {
|
|
2159
|
-
| Some(current) if through > current =>
|
|
2160
|
-
{...fetchState, blockRegisterThrough: through}->updateInternal
|
|
2161
|
-
| _ => fetchState
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
|
-
// How far block-handler register passes can run with no response to run them
|
|
2165
|
-
// with: through the block every partition has fetched, or the head when there
|
|
2166
|
-
// is no partition, and never past the chain's end block.
|
|
2167
|
-
let blockRegisterFrontier = (fetchState: t) =>
|
|
2168
|
-
fetchState->capAtEndBlock(
|
|
2169
|
-
switch fetchState.optimizedPartitions->OptimizedPartitions.getLatestFullyFetchedBlock {
|
|
2170
|
-
| Some(block) => Pervasives.min(block, fetchState.knownHeight)
|
|
2171
|
-
| None => fetchState.knownHeight
|
|
2172
|
-
},
|
|
2173
|
-
)
|
|
2174
|
-
|
|
2175
2002
|
type nextQuery =
|
|
2176
2003
|
| WaitingForNewBlock
|
|
2177
2004
|
| NothingToQuery
|
|
@@ -2612,6 +2439,20 @@ let acceptCandidates = (
|
|
|
2612
2439
|
}
|
|
2613
2440
|
}
|
|
2614
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
|
+
|
|
2615
2456
|
// Candidate queries are sized against chainTargetBlock, the soft querying
|
|
2616
2457
|
// horizon the owning chain wants to reach this tick — derived by ChainState
|
|
2617
2458
|
// from its share of the indexer-wide buffer budget and its chain-level event
|
|
@@ -2640,7 +2481,7 @@ let acceptCandidates = (
|
|
|
2640
2481
|
// rangeTargetDensity × (chainTargetBlock − fromBlock + 1) / inRangeCount — so
|
|
2641
2482
|
// unknown-density partitions probe in parallel within one budget.
|
|
2642
2483
|
let getNextQuery = (
|
|
2643
|
-
{optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight, endBlock}: t,
|
|
2484
|
+
{optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight, endBlock} as fetchState: t,
|
|
2644
2485
|
~chainTargetBlock: int,
|
|
2645
2486
|
~chainTargetItems: float,
|
|
2646
2487
|
) => {
|
|
@@ -2648,7 +2489,8 @@ let getNextQuery = (
|
|
|
2648
2489
|
if headBlockNumber <= 0 {
|
|
2649
2490
|
WaitingForNewBlock
|
|
2650
2491
|
} else {
|
|
2651
|
-
let
|
|
2492
|
+
let caughtUpBlockNumber = headBlockNumber - fetchState->blocksBehindHeadAllowedByThrottle
|
|
2493
|
+
let isOnBlockBehindTheHead = latestOnBlockBlockNumber < caughtUpBlockNumber
|
|
2652
2494
|
let shouldWaitForNewBlock = ref(
|
|
2653
2495
|
switch endBlock {
|
|
2654
2496
|
| Some(endBlock) => headBlockNumber < endBlock
|
|
@@ -2693,7 +2535,7 @@ let getNextQuery = (
|
|
|
2693
2535
|
}
|
|
2694
2536
|
}
|
|
2695
2537
|
inFlightCounts->Array.setUnsafe(idx, inFlightCount.contents)
|
|
2696
|
-
if p.mutPendingQueries->Array.length > 0 || p.latestFetchedBlock <
|
|
2538
|
+
if p.mutPendingQueries->Array.length > 0 || p.latestFetchedBlock < caughtUpBlockNumber {
|
|
2697
2539
|
// Even if there are some partitions waiting for the new block
|
|
2698
2540
|
// We still want to wait for all partitions reaching the head
|
|
2699
2541
|
// because they might update knownHeight in their response
|
|
@@ -2872,10 +2714,10 @@ let make = (
|
|
|
2872
2714
|
~progressBlockNumber=startBlock - 1,
|
|
2873
2715
|
~onBlockRegistrations=[],
|
|
2874
2716
|
~blockLag=0,
|
|
2717
|
+
~blockThrottle=0,
|
|
2875
2718
|
~firstEventBlock=None,
|
|
2876
2719
|
~clientFilterAddressThreshold=None,
|
|
2877
2720
|
~isResumed=false,
|
|
2878
|
-
~deferCreationBlockEvents=false,
|
|
2879
2721
|
): t => {
|
|
2880
2722
|
let latestFetchedBlock = progressBlockNumber
|
|
2881
2723
|
|
|
@@ -2955,7 +2797,6 @@ let make = (
|
|
|
2955
2797
|
})
|
|
2956
2798
|
|
|
2957
2799
|
let dynamicContracts = Utils.Set.make()
|
|
2958
|
-
let clientFilteredContracts = Utils.Set.make()
|
|
2959
2800
|
let registeringSetsByContract = Dict.make()
|
|
2960
2801
|
|
|
2961
2802
|
// What each contract needs a partition for is read back off the store rather
|
|
@@ -2979,26 +2820,24 @@ let make = (
|
|
|
2979
2820
|
}
|
|
2980
2821
|
})
|
|
2981
2822
|
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
switch clientFilterAddressThreshold {
|
|
2986
|
-
| Some(threshold) =>
|
|
2987
|
-
registeringSetsByContract->Utils.Dict.forEachWithKey((set, contractName) => {
|
|
2988
|
-
let addressCount = set->AddressSet.size
|
|
2989
|
-
if addressCount > threshold {
|
|
2990
|
-
clientFilteredContracts->addClientFilteredContract(
|
|
2991
|
-
~contractName,
|
|
2992
|
-
~onNotice,
|
|
2993
|
-
~addressCount,
|
|
2994
|
-
~threshold,
|
|
2995
|
-
~isAlreadyReported=isResumed,
|
|
2996
|
-
)
|
|
2997
|
-
}
|
|
2998
|
-
})
|
|
2999
|
-
| None => ()
|
|
2823
|
+
let clientFilterPolicy = {
|
|
2824
|
+
addressThreshold: clientFilterAddressThreshold,
|
|
2825
|
+
allDynamicContracts: false,
|
|
3000
2826
|
}
|
|
3001
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
|
+
|
|
3002
2841
|
let optimizedPartitions = createPartitions(
|
|
3003
2842
|
~registeringSetsByContract,
|
|
3004
2843
|
~addressStore,
|
|
@@ -3031,14 +2870,6 @@ let make = (
|
|
|
3031
2870
|
// fetching, so without seeding the buffer here getNextQuery would return
|
|
3032
2871
|
// NothingToQuery and the indexer would get stuck.
|
|
3033
2872
|
let buffer = []
|
|
3034
|
-
// Every block up to the progress block was processed, so its register passes
|
|
3035
|
-
// ran and what they registered is in the seeded rows.
|
|
3036
|
-
let blockRegisterThrough =
|
|
3037
|
-
onBlockRegistrations->Array.some((r: Internal.onBlockRegistration) =>
|
|
3038
|
-
r.contractRegister !== None
|
|
3039
|
-
)
|
|
3040
|
-
? Some(progressBlockNumber)
|
|
3041
|
-
: None
|
|
3042
2873
|
let latestOnBlockBlockNumber = switch onBlockRegistrations {
|
|
3043
2874
|
// As updateInternal keeps it: with nothing to generate per block the pointer
|
|
3044
2875
|
// is the head cap on the buffer frontier, and left at the progress block it
|
|
@@ -3051,10 +2882,6 @@ let make = (
|
|
|
3051
2882
|
| None => knownHeight
|
|
3052
2883
|
| Some(latestFullyFetchedBlock) => Pervasives.min(latestFullyFetchedBlock, knownHeight)
|
|
3053
2884
|
}
|
|
3054
|
-
let maxBlockNumber = switch blockRegisterThrough {
|
|
3055
|
-
| Some(through) => Pervasives.min(maxBlockNumber, through)
|
|
3056
|
-
| None => maxBlockNumber
|
|
3057
|
-
}
|
|
3058
2885
|
appendOnBlockItems(
|
|
3059
2886
|
~mutItems=buffer,
|
|
3060
2887
|
~onBlockRegistrations,
|
|
@@ -3074,14 +2901,13 @@ let make = (
|
|
|
3074
2901
|
latestOnBlockBlockNumber,
|
|
3075
2902
|
normalSelection,
|
|
3076
2903
|
blockLag,
|
|
2904
|
+
blockThrottle,
|
|
3077
2905
|
onBlockRegistrations,
|
|
3078
2906
|
maxOnBlockBufferSize,
|
|
3079
2907
|
knownHeight,
|
|
3080
2908
|
buffer,
|
|
3081
2909
|
firstEventBlock,
|
|
3082
|
-
|
|
3083
|
-
creationBlocks: ?(deferCreationBlockEvents ? Some(Dict.make()) : None),
|
|
3084
|
-
?blockRegisterThrough,
|
|
2910
|
+
clientFilterPolicy,
|
|
3085
2911
|
}
|
|
3086
2912
|
|
|
3087
2913
|
fetchState
|
|
@@ -3233,13 +3059,6 @@ let rollback = (
|
|
|
3233
3059
|
fetchState.latestOnBlockBlockNumber,
|
|
3234
3060
|
targetBlockNumber,
|
|
3235
3061
|
),
|
|
3236
|
-
// The passes past the target run again on the refetched blocks: what they
|
|
3237
|
-
// registered was pruned from the store above.
|
|
3238
|
-
blockRegisterThrough: ?(
|
|
3239
|
-
fetchState.blockRegisterThrough->Option.map(through =>
|
|
3240
|
-
Pervasives.min(through, targetBlockNumber)
|
|
3241
|
-
)
|
|
3242
|
-
),
|
|
3243
3062
|
}->updateInternal(
|
|
3244
3063
|
~optimizedPartitions,
|
|
3245
3064
|
// Filtering the sorted buffer keeps it sorted and deduped.
|
|
@@ -3301,15 +3120,37 @@ let isActivelyIndexing = ({endBlock} as fetchState: t) => {
|
|
|
3301
3120
|
// True once the fetch frontier has reached the (lagged) head or endBlock,
|
|
3302
3121
|
// regardless of whether the buffer has been consumed yet. Unlike
|
|
3303
3122
|
// isReadyToEnterReorgThreshold, fetched-but-unprocessed items still count.
|
|
3304
|
-
let isFetchingAtHead = ({endBlock,
|
|
3123
|
+
let isFetchingAtHead = ({endBlock, knownHeight} as fetchState: t) => {
|
|
3305
3124
|
let bufferBlockNumber = fetchState->bufferBlockNumber
|
|
3306
3125
|
knownHeight !== 0 &&
|
|
3307
3126
|
switch endBlock {
|
|
3308
3127
|
| Some(endBlock) if bufferBlockNumber >= endBlock => true
|
|
3309
|
-
| _ => bufferBlockNumber >=
|
|
3128
|
+
| _ => bufferBlockNumber >= fetchState->headFetchTarget
|
|
3310
3129
|
}
|
|
3311
3130
|
}
|
|
3312
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
|
+
|
|
3313
3154
|
// Frontier at (or within `tolerance` of) the lagged head with no processable
|
|
3314
3155
|
// items left — the moment the chain can cross into the reorg threshold.
|
|
3315
3156
|
// `tolerance` absorbs the head advancing between a chain catching up and this
|