envio 3.5.0-alpha.2 → 3.5.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/src/BatchProcessing.res +14 -0
- package/src/BatchProcessing.res.mjs +8 -0
- package/src/ChainState.res +10 -4
- package/src/ChainState.res.mjs +7 -6
- package/src/ChainState.resi +1 -1
- package/src/Config.res +2 -2
- package/src/Config.res.mjs +2 -2
- package/src/CrossChainState.res +33 -10
- package/src/CrossChainState.res.mjs +21 -6
- package/src/CrossChainState.resi +3 -0
- package/src/FetchState.res +230 -66
- package/src/FetchState.res.mjs +213 -67
- package/src/FinalizeBackfill.res +34 -0
- package/src/FinalizeBackfill.res.mjs +26 -0
- package/src/InMemoryTable.res +15 -15
- package/src/InMemoryTable.res.mjs +14 -14
- package/src/IndexerState.res +12 -0
- package/src/IndexerState.res.mjs +19 -0
- package/src/IndexerState.resi +3 -0
- package/src/LoadLayer.res +9 -1
- package/src/LoadLayer.res.mjs +1 -0
- package/src/Persistence.res +11 -0
- package/src/PgStorage.res +356 -35
- package/src/PgStorage.res.mjs +237 -24
- package/src/TestIndexer.res +3 -0
- package/src/TestIndexer.res.mjs +2 -0
- package/src/db/EntityFilter.res +0 -4
- package/src/db/EntityFilter.res.mjs +1 -8
- package/src/db/IndexRegistry.res +219 -0
- package/src/db/IndexRegistry.res.mjs +195 -0
- package/src/db/InternalTable.res +7 -0
- package/src/db/InternalTable.res.mjs +7 -0
- package/src/db/Table.res +13 -13
- package/src/db/Table.res.mjs +12 -12
package/src/FetchState.res
CHANGED
|
@@ -270,6 +270,47 @@ module OptimizedPartitions = {
|
|
|
270
270
|
let ascSortFn = (a, b) =>
|
|
271
271
|
Int.compare(a.latestFetchedBlock.blockNumber, b.latestFetchedBlock.blockNumber)
|
|
272
272
|
|
|
273
|
+
// Contracts a standing address-free partition already fetches client-side.
|
|
274
|
+
// Addresses registered for them after that partition passed get a normal
|
|
275
|
+
// address-bound partition which dies once it catches up (see make), instead
|
|
276
|
+
// of being folded into the address-free one.
|
|
277
|
+
let anchoredContracts = (partitions: array<partition>) => {
|
|
278
|
+
let set = Utils.Set.make()
|
|
279
|
+
partitions->Array.forEach(p =>
|
|
280
|
+
switch (p.mergeBlock, p.selection.clientFilteredContracts) {
|
|
281
|
+
| (None, Some(contractNames)) =>
|
|
282
|
+
contractNames->Array.forEach(name => set->Utils.Set.add(name)->ignore)
|
|
283
|
+
| _ => ()
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
set
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// The furthest block an address-free partition's already-dispatched queries
|
|
290
|
+
// can deliver without the addresses registered from now on. A settled query
|
|
291
|
+
// claims only what it actually fetched — the rest of its range is re-queried
|
|
292
|
+
// later, by then against the updated address store — while an in-flight
|
|
293
|
+
// bounded query claims its whole toBlock. An in-flight unbounded query has no
|
|
294
|
+
// ceiling at all, so nothing is safe to stop a catch-up partition at yet.
|
|
295
|
+
let getAnchorSafeBlock = (p: partition) => {
|
|
296
|
+
let safeRef = ref(Some(p.latestFetchedBlock.blockNumber))
|
|
297
|
+
p.mutPendingQueries->Array.forEach(pq =>
|
|
298
|
+
switch (safeRef.contents, pq) {
|
|
299
|
+
| (None, _) => ()
|
|
300
|
+
| (Some(safe), {fetchedBlock: Some({blockNumber})}) =>
|
|
301
|
+
if blockNumber > safe {
|
|
302
|
+
safeRef := Some(blockNumber)
|
|
303
|
+
}
|
|
304
|
+
| (Some(safe), {toBlock: Some(toBlock)}) =>
|
|
305
|
+
if toBlock > safe {
|
|
306
|
+
safeRef := Some(toBlock)
|
|
307
|
+
}
|
|
308
|
+
| (Some(_), _) => safeRef := None
|
|
309
|
+
}
|
|
310
|
+
)
|
|
311
|
+
safeRef.contents
|
|
312
|
+
}
|
|
313
|
+
|
|
273
314
|
/**
|
|
274
315
|
* Optimizes partitions by finding opportunities to merge partitions that
|
|
275
316
|
* are behind other partitions with same/superset of contract names.
|
|
@@ -288,19 +329,49 @@ module OptimizedPartitions = {
|
|
|
288
329
|
let mergingPartitions = Dict.make()
|
|
289
330
|
let nextPartitionIndexRef = ref(nextPartitionIndex)
|
|
290
331
|
|
|
332
|
+
// Where a catch-up partition for a client-filtered contract may stop, keyed
|
|
333
|
+
// by contract name. A contract absent from the dict while present in
|
|
334
|
+
// anchoredContractsSet has an unbounded query in flight on its address-free
|
|
335
|
+
// partition — its catch-up can't be bounded yet, and a later call will bound it.
|
|
336
|
+
let anchorSafeBlocks = Dict.make()
|
|
337
|
+
let anchoredContractsSet = Utils.Set.make()
|
|
338
|
+
if clientFilteredContracts->Utils.Set.size > 0 {
|
|
339
|
+
partitions->Array.forEach(p =>
|
|
340
|
+
switch (p.mergeBlock, p.selection.clientFilteredContracts) {
|
|
341
|
+
| (None, Some(contractNames)) =>
|
|
342
|
+
let safeBlock = p->getAnchorSafeBlock
|
|
343
|
+
contractNames->Array.forEach(name => {
|
|
344
|
+
anchoredContractsSet->Utils.Set.add(name)->ignore
|
|
345
|
+
switch safeBlock {
|
|
346
|
+
| Some(safeBlock) => anchorSafeBlocks->Dict.set(name, safeBlock)
|
|
347
|
+
| None => ()
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
| _ => ()
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
}
|
|
354
|
+
|
|
291
355
|
for idx in 0 to partitions->Array.length - 1 {
|
|
292
356
|
let p = partitions->Array.getUnsafe(idx)
|
|
293
357
|
switch p {
|
|
358
|
+
// For now don't merge partitions with mergeBlock,
|
|
359
|
+
// assuming they are already merged,
|
|
360
|
+
// TODO: Although there might be cases with too far away mergeBlock,
|
|
361
|
+
// which is worth merging.
|
|
362
|
+
// A partition already at or past its merge block is done — normally
|
|
363
|
+
// handleQueryResponse removes it when the response lands, but a rollback
|
|
364
|
+
// can cap the merge block at the rolled-back frontier, leaving no
|
|
365
|
+
// response to ever remove it on.
|
|
366
|
+
| {mergeBlock: Some(mergeBlock)} =>
|
|
367
|
+
if p.latestFetchedBlock.blockNumber < mergeBlock {
|
|
368
|
+
newPartitions->Array.push(p)->ignore
|
|
369
|
+
}
|
|
294
370
|
// Since it's not a dynamic contract partition,
|
|
295
371
|
// there's no need for merge logic
|
|
296
372
|
| {dynamicContract: None}
|
|
297
373
|
| // Wildcard doesn't need merging
|
|
298
|
-
{selection: {dependsOnAddresses: false}}
|
|
299
|
-
| // For now don't merge partitions with mergeBlock,
|
|
300
|
-
// assuming they are already merged,
|
|
301
|
-
// TODO: Although there might be cases with too far away mergeBlock,
|
|
302
|
-
// which is worth merging
|
|
303
|
-
{mergeBlock: Some(_)} =>
|
|
374
|
+
{selection: {dependsOnAddresses: false}} =>
|
|
304
375
|
newPartitions->Array.push(p)->ignore
|
|
305
376
|
| {dynamicContract: Some(contractName)} =>
|
|
306
377
|
let pAddressesCount = p.addresses->AddressSet.countFor(contractName)
|
|
@@ -398,14 +469,40 @@ module OptimizedPartitions = {
|
|
|
398
469
|
newPartitions->Array.push(currentPRef.contents)->ignore
|
|
399
470
|
}
|
|
400
471
|
|
|
472
|
+
// A dynamic partition for a contract the address-free partition already
|
|
473
|
+
// fetches is a catch-up for addresses registered after that partition
|
|
474
|
+
// passed them. It merges by disappearing once it reaches the last block
|
|
475
|
+
// that partition's dispatched queries could have missed them on — its
|
|
476
|
+
// addresses are in the chain's store, so there is nothing to hand over.
|
|
477
|
+
let finalPartitions = if anchoredContractsSet->Utils.Set.size === 0 {
|
|
478
|
+
newPartitions
|
|
479
|
+
} else {
|
|
480
|
+
let anchored = []
|
|
481
|
+
newPartitions->Array.forEach(p =>
|
|
482
|
+
switch p {
|
|
483
|
+
| {dynamicContract: Some(contractName), mergeBlock: None}
|
|
484
|
+
if anchoredContractsSet->Utils.Set.has(contractName) =>
|
|
485
|
+
switch anchorSafeBlocks->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
486
|
+
| None => anchored->Array.push(p)->ignore
|
|
487
|
+
| Some(anchorSafeBlock) =>
|
|
488
|
+
if p.latestFetchedBlock.blockNumber < anchorSafeBlock {
|
|
489
|
+
anchored->Array.push({...p, mergeBlock: Some(anchorSafeBlock)})->ignore
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
| _ => anchored->Array.push(p)->ignore
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
anchored
|
|
496
|
+
}
|
|
497
|
+
|
|
401
498
|
// Sort partitions by latestFetchedBlock ascending
|
|
402
|
-
let _ =
|
|
499
|
+
let _ = finalPartitions->Array.sort(ascSortFn)
|
|
403
500
|
|
|
404
|
-
let partitionsCount =
|
|
501
|
+
let partitionsCount = finalPartitions->Array.length
|
|
405
502
|
let idsInAscOrder = Utils.Array.jsArrayCreate(partitionsCount)
|
|
406
503
|
let entities = Dict.make()
|
|
407
504
|
for idx in 0 to partitionsCount - 1 {
|
|
408
|
-
let p =
|
|
505
|
+
let p = finalPartitions->Array.getUnsafe(idx)
|
|
409
506
|
idsInAscOrder->Array.setUnsafe(idx, p.id)
|
|
410
507
|
entities->Dict.set(p.id, p)
|
|
411
508
|
}
|
|
@@ -951,18 +1048,24 @@ let addClientFilteredContract = (
|
|
|
951
1048
|
~chainId,
|
|
952
1049
|
~addressCount,
|
|
953
1050
|
~threshold,
|
|
1051
|
+
// A resumed fetch state re-derives the switch from the persisted addresses,
|
|
1052
|
+
// but it already happened - and was logged - in the run that crossed the
|
|
1053
|
+
// threshold.
|
|
1054
|
+
~shouldLog=true,
|
|
954
1055
|
) => {
|
|
955
1056
|
clientFilteredContracts->Utils.Set.add(contractName)->ignore
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1057
|
+
if shouldLog {
|
|
1058
|
+
Logging.createChild(
|
|
1059
|
+
~params={
|
|
1060
|
+
"chainId": chainId,
|
|
1061
|
+
"contractName": contractName,
|
|
1062
|
+
"addressCount": addressCount,
|
|
1063
|
+
"threshold": threshold,
|
|
1064
|
+
},
|
|
1065
|
+
)->Logging.childTrace(
|
|
1066
|
+
"Switching contract to client-side address filtering: registered address count crossed the server-side threshold.",
|
|
1067
|
+
)
|
|
1068
|
+
}
|
|
966
1069
|
}
|
|
967
1070
|
|
|
968
1071
|
// The block a partition will have fetched to once everything on its pending
|
|
@@ -998,6 +1101,10 @@ let claimedFetchedBlock = (p: partition, ~knownHeight) =>
|
|
|
998
1101
|
// it on arrival. The overlap it re-delivers is deduped by mergeIntoBuffer, and
|
|
999
1102
|
// the re-fetch doubles as history for freshly registered addresses: events
|
|
1000
1103
|
// dropped before the address was registered now pass the address gate.
|
|
1104
|
+
// - A dynamic partition for a contract the standing partition already covers is
|
|
1105
|
+
// left alone: it is a catch-up for addresses registered after that partition
|
|
1106
|
+
// passed them, and OptimizedPartitions.make bounds it against the standing
|
|
1107
|
+
// partition's own claims instead.
|
|
1001
1108
|
// - A partition mixing client-filtered and server-side contracts stays,
|
|
1002
1109
|
// stripped of the client-filtered contracts' addresses — the address-free
|
|
1003
1110
|
// partition covers those logs, so fetching them server-side too would only
|
|
@@ -1014,6 +1121,10 @@ let collapseClientFilteredContracts = (
|
|
|
1014
1121
|
~normalSelection: selection,
|
|
1015
1122
|
~nextPartitionIndexRef: ref<int>,
|
|
1016
1123
|
~addressStore: AddressStore.t,
|
|
1124
|
+
// Frontiers of the addresses that were never given a server-side partition
|
|
1125
|
+
// because their contract is already client-filtered. They stand in for the
|
|
1126
|
+
// partitions that would otherwise have been created only to be absorbed here.
|
|
1127
|
+
~clientFilteredFrontiers: array<blockNumberAndTimestamp>=[],
|
|
1017
1128
|
~knownHeight: int,
|
|
1018
1129
|
) => {
|
|
1019
1130
|
if clientFilteredContracts->Utils.Set.size === 0 {
|
|
@@ -1024,6 +1135,7 @@ let collapseClientFilteredContracts = (
|
|
|
1024
1135
|
let backfills = []
|
|
1025
1136
|
let absorbedPartitions = []
|
|
1026
1137
|
let strippedFrontiers = []
|
|
1138
|
+
let anchoredContracts = partitions->OptimizedPartitions.anchoredContracts
|
|
1027
1139
|
|
|
1028
1140
|
partitions->Array.forEach(p =>
|
|
1029
1141
|
switch p {
|
|
@@ -1039,6 +1151,17 @@ let collapseClientFilteredContracts = (
|
|
|
1039
1151
|
contractNames->Array.filter(c => !(clientFilteredContracts->Utils.Set.has(c)))
|
|
1040
1152
|
if serverSideNames->Array.length === contractNames->Array.length {
|
|
1041
1153
|
kept->Array.push(p)->ignore
|
|
1154
|
+
} else if (
|
|
1155
|
+
switch p.dynamicContract {
|
|
1156
|
+
| Some(contractName) => anchoredContracts->Utils.Set.has(contractName)
|
|
1157
|
+
| None => false
|
|
1158
|
+
}
|
|
1159
|
+
) {
|
|
1160
|
+
// A catch-up partition for addresses registered after the address-free
|
|
1161
|
+
// partition already covered their contract. It is the correctness
|
|
1162
|
+
// barrier for those addresses until it catches up — absorbing it would
|
|
1163
|
+
// hand that job back to a guessed ceiling.
|
|
1164
|
+
kept->Array.push(p)->ignore
|
|
1042
1165
|
} else if serverSideNames->Utils.Array.isEmpty {
|
|
1043
1166
|
absorbedPartitions->Array.push(p)->ignore
|
|
1044
1167
|
} else {
|
|
@@ -1060,6 +1183,7 @@ let collapseClientFilteredContracts = (
|
|
|
1060
1183
|
if (
|
|
1061
1184
|
absorbedPartitions->Utils.Array.isEmpty &&
|
|
1062
1185
|
strippedFrontiers->Utils.Array.isEmpty &&
|
|
1186
|
+
clientFilteredFrontiers->Utils.Array.isEmpty &&
|
|
1063
1187
|
!selectionChanged
|
|
1064
1188
|
) {
|
|
1065
1189
|
// Nothing to fold in and no newly-switched contract: leave the standing
|
|
@@ -1075,6 +1199,7 @@ let collapseClientFilteredContracts = (
|
|
|
1075
1199
|
absorbedPartitions->Array.forEach(p => considerFrontier(p.latestFetchedBlock))
|
|
1076
1200
|
backfills->Array.forEach(p => considerFrontier(p.latestFetchedBlock))
|
|
1077
1201
|
strippedFrontiers->Array.forEach(considerFrontier)
|
|
1202
|
+
clientFilteredFrontiers->Array.forEach(considerFrontier)
|
|
1078
1203
|
|
|
1079
1204
|
let regByIndex = Dict.make()
|
|
1080
1205
|
let addRegs = (regs: array<Internal.onEventRegistration>) =>
|
|
@@ -1199,68 +1324,96 @@ OptimizedPartitions.t => {
|
|
|
1199
1324
|
// ── Phase 1: Create per-contract-name partitions ──
|
|
1200
1325
|
let dynamicPartitions = []
|
|
1201
1326
|
let nonDynamicPartitions = []
|
|
1327
|
+
let clientFilteredFrontiers = []
|
|
1328
|
+
|
|
1329
|
+
// Contracts an address-free partition already fetches. Their new addresses
|
|
1330
|
+
// need a partition of their own: the address-free partition passed the blocks
|
|
1331
|
+
// they were registered at without them in the store.
|
|
1332
|
+
let anchoredContracts = existingPartitions->OptimizedPartitions.anchoredContracts
|
|
1202
1333
|
|
|
1203
1334
|
let contractNames = registeringSetsByContract->Dict.keysToArray
|
|
1204
1335
|
for cIdx in 0 to contractNames->Array.length - 1 {
|
|
1205
1336
|
let contractName = contractNames->Array.getUnsafe(cIdx)
|
|
1206
1337
|
let contractSet = registeringSetsByContract->Dict.getUnsafe(contractName)
|
|
1207
1338
|
|
|
1208
|
-
let
|
|
1339
|
+
let isAnchored = anchoredContracts->Utils.Set.has(contractName)
|
|
1340
|
+
// A catch-up partition must go through the dynamic merge logic — that's
|
|
1341
|
+
// what bounds it against its anchor and removes it once it catches up.
|
|
1342
|
+
let isDynamic = dynamicContracts->Utils.Set.has(contractName) || isAnchored
|
|
1209
1343
|
let partitions = isDynamic ? dynamicPartitions : nonDynamicPartitions
|
|
1210
1344
|
|
|
1211
1345
|
// A set is ordered by effectiveStartBlock, so its start-block groups are
|
|
1212
1346
|
// ascending and each group's addresses are a contiguous slice.
|
|
1213
1347
|
let groups = contractSet->AddressSet.startBlockGroups
|
|
1214
|
-
let offsetRef = ref(0)
|
|
1215
|
-
let groupIdx = ref(0)
|
|
1216
|
-
while groupIdx.contents < groups->Array.length {
|
|
1217
|
-
let startBlock = (groups->Array.getUnsafe(groupIdx.contents)).startBlock
|
|
1218
|
-
// Addresses with different start blocks within range share a partition;
|
|
1219
|
-
// events before each address's effectiveStartBlock are dropped by the
|
|
1220
|
-
// source's address gate.
|
|
1221
|
-
let countRef = ref(0)
|
|
1222
|
-
let nextIdx = ref(groupIdx.contents)
|
|
1223
|
-
let joining = ref(true)
|
|
1224
|
-
while joining.contents && nextIdx.contents < groups->Array.length {
|
|
1225
|
-
let group = groups->Array.getUnsafe(nextIdx.contents)
|
|
1226
|
-
if group.startBlock - startBlock < OptimizedPartitions.tooFarBlockRange {
|
|
1227
|
-
countRef := countRef.contents + group.count
|
|
1228
|
-
nextIdx := nextIdx.contents + 1
|
|
1229
|
-
} else {
|
|
1230
|
-
joining := false
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
1348
|
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
selection: normalSelection,
|
|
1248
|
-
dynamicContract: isDynamic ? Some(contractName) : None,
|
|
1249
|
-
addresses: pAddresses,
|
|
1250
|
-
mergeBlock: None,
|
|
1251
|
-
mutPendingQueries: [],
|
|
1252
|
-
sourceRangeCapacity: 0,
|
|
1253
|
-
prevSourceRangeCapacity: 0,
|
|
1254
|
-
eventDensity: None,
|
|
1255
|
-
latestSourceRangeCapacityUpdateBlock: 0,
|
|
1349
|
+
if clientFilteredContracts->Utils.Set.has(contractName) && !isAnchored {
|
|
1350
|
+
// The contract is switching to client-side filtering in this very call, so
|
|
1351
|
+
// the collapse below folds everything it has into the address-free
|
|
1352
|
+
// partition anyway. Chunking these addresses by maxAddrInPartition would
|
|
1353
|
+
// only build partitions for it to absorb - hundreds of them for a contract
|
|
1354
|
+
// big enough to be client-filtered in the first place. All the collapse
|
|
1355
|
+
// needs is the earliest block the addresses aren't covered from, which is
|
|
1356
|
+
// the first group's since groups are ascending.
|
|
1357
|
+
switch groups->Array.get(0) {
|
|
1358
|
+
| Some({startBlock}) =>
|
|
1359
|
+
clientFilteredFrontiers->Array.push({
|
|
1360
|
+
blockNumber: Pervasives.max(startBlock - 1, progressBlockNumber),
|
|
1361
|
+
blockTimestamp: 0,
|
|
1256
1362
|
})
|
|
1257
|
-
|
|
1258
|
-
chunkOffsetRef := chunkOffsetRef.contents + take
|
|
1259
|
-
remainingRef := remainingRef.contents - take
|
|
1363
|
+
| None => ()
|
|
1260
1364
|
}
|
|
1365
|
+
} else {
|
|
1366
|
+
let offsetRef = ref(0)
|
|
1367
|
+
let groupIdx = ref(0)
|
|
1368
|
+
while groupIdx.contents < groups->Array.length {
|
|
1369
|
+
let startBlock = (groups->Array.getUnsafe(groupIdx.contents)).startBlock
|
|
1370
|
+
// Addresses with different start blocks within range share a partition;
|
|
1371
|
+
// events before each address's effectiveStartBlock are dropped by the
|
|
1372
|
+
// source's address gate.
|
|
1373
|
+
let countRef = ref(0)
|
|
1374
|
+
let nextIdx = ref(groupIdx.contents)
|
|
1375
|
+
let joining = ref(true)
|
|
1376
|
+
while joining.contents && nextIdx.contents < groups->Array.length {
|
|
1377
|
+
let group = groups->Array.getUnsafe(nextIdx.contents)
|
|
1378
|
+
if group.startBlock - startBlock < OptimizedPartitions.tooFarBlockRange {
|
|
1379
|
+
countRef := countRef.contents + group.count
|
|
1380
|
+
nextIdx := nextIdx.contents + 1
|
|
1381
|
+
} else {
|
|
1382
|
+
joining := false
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
let latestFetchedBlock = {
|
|
1387
|
+
blockNumber: Pervasives.max(startBlock - 1, progressBlockNumber),
|
|
1388
|
+
blockTimestamp: 0,
|
|
1389
|
+
}
|
|
1390
|
+
let remainingRef = ref(countRef.contents)
|
|
1391
|
+
let chunkOffsetRef = ref(offsetRef.contents)
|
|
1392
|
+
while remainingRef.contents > 0 {
|
|
1393
|
+
let take = Pervasives.min(remainingRef.contents, maxAddrInPartition)
|
|
1394
|
+
let pAddresses =
|
|
1395
|
+
contractSet->AddressSet.slice(~offset=chunkOffsetRef.contents, ~limit=Some(take))
|
|
1396
|
+
partitions->Array.push({
|
|
1397
|
+
id: nextPartitionIndexRef.contents->Int.toString,
|
|
1398
|
+
latestFetchedBlock,
|
|
1399
|
+
selection: normalSelection,
|
|
1400
|
+
dynamicContract: isDynamic ? Some(contractName) : None,
|
|
1401
|
+
addresses: pAddresses,
|
|
1402
|
+
mergeBlock: None,
|
|
1403
|
+
mutPendingQueries: [],
|
|
1404
|
+
sourceRangeCapacity: 0,
|
|
1405
|
+
prevSourceRangeCapacity: 0,
|
|
1406
|
+
eventDensity: None,
|
|
1407
|
+
latestSourceRangeCapacityUpdateBlock: 0,
|
|
1408
|
+
})
|
|
1409
|
+
nextPartitionIndexRef := nextPartitionIndexRef.contents + 1
|
|
1410
|
+
chunkOffsetRef := chunkOffsetRef.contents + take
|
|
1411
|
+
remainingRef := remainingRef.contents - take
|
|
1412
|
+
}
|
|
1261
1413
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1414
|
+
offsetRef := offsetRef.contents + countRef.contents
|
|
1415
|
+
groupIdx := nextIdx.contents
|
|
1416
|
+
}
|
|
1264
1417
|
}
|
|
1265
1418
|
}
|
|
1266
1419
|
|
|
@@ -1324,6 +1477,7 @@ OptimizedPartitions.t => {
|
|
|
1324
1477
|
~normalSelection,
|
|
1325
1478
|
~nextPartitionIndexRef,
|
|
1326
1479
|
~addressStore,
|
|
1480
|
+
~clientFilteredFrontiers,
|
|
1327
1481
|
~knownHeight,
|
|
1328
1482
|
)
|
|
1329
1483
|
OptimizedPartitions.make(
|
|
@@ -2343,6 +2497,7 @@ let make = (
|
|
|
2343
2497
|
~blockLag=0,
|
|
2344
2498
|
~firstEventBlock=None,
|
|
2345
2499
|
~clientFilterAddressThreshold=None,
|
|
2500
|
+
~isResumed=false,
|
|
2346
2501
|
): t => {
|
|
2347
2502
|
let latestFetchedBlock = {
|
|
2348
2503
|
blockTimestamp: 0,
|
|
@@ -2438,6 +2593,7 @@ let make = (
|
|
|
2438
2593
|
~chainId,
|
|
2439
2594
|
~addressCount,
|
|
2440
2595
|
~threshold,
|
|
2596
|
+
~shouldLog=!isResumed,
|
|
2441
2597
|
)
|
|
2442
2598
|
}
|
|
2443
2599
|
})
|
|
@@ -2586,6 +2742,14 @@ let rollback = (fetchState: t, ~addressStore: AddressStore.t, ~targetBlockNumber
|
|
|
2586
2742
|
latestFetchedBlock: p.latestFetchedBlock.blockNumber > targetBlockNumber
|
|
2587
2743
|
? {blockNumber: targetBlockNumber, blockTimestamp: 0}
|
|
2588
2744
|
: p.latestFetchedBlock,
|
|
2745
|
+
// Everything above the target is refetched by whichever partition this
|
|
2746
|
+
// one was catching up to, so there is nothing left to catch up on past
|
|
2747
|
+
// it. createPartitions drops the partition outright when the capped
|
|
2748
|
+
// block is already reached.
|
|
2749
|
+
mergeBlock: switch p.mergeBlock {
|
|
2750
|
+
| Some(mergeBlock) if mergeBlock > targetBlockNumber => Some(targetBlockNumber)
|
|
2751
|
+
| other => other
|
|
2752
|
+
},
|
|
2589
2753
|
mutPendingQueries: rollbackPendingQueries(p.mutPendingQueries, ~targetBlockNumber),
|
|
2590
2754
|
})
|
|
2591
2755
|
->ignore
|