envio 3.12.0 → 3.12.1
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/ChainFetching.res +7 -3
- package/src/ChainFetching.res.mjs +1 -1
- package/src/ChainState.res +12 -3
- package/src/ChainState.res.mjs +3 -3
- package/src/ChainState.resi +1 -1
- package/src/CrossChainState.res +1 -1
- package/src/CrossChainState.res.mjs +1 -1
- package/src/FetchState.res +51 -46
- package/src/FetchState.res.mjs +54 -36
- package/src/InMemoryTable.res +155 -67
- package/src/InMemoryTable.res.mjs +151 -60
- package/src/LoadLayer.res +57 -34
- package/src/LoadLayer.res.mjs +45 -62
- package/src/LoadLayer.resi +1 -1
- package/src/PgStorage.res +92 -62
- package/src/PgStorage.res.mjs +77 -50
- package/src/TestIndexer.res +9 -25
- package/src/TestIndexer.res.mjs +4 -3
- package/src/UserContext.res +13 -32
- package/src/UserContext.res.mjs +1 -7
- package/src/Utils.res +1 -4
- package/src/Utils.res.mjs +7 -16
- package/src/db/EntityFilter.res +487 -275
- package/src/db/EntityFilter.res.mjs +557 -309
- package/src/db/Table.res +21 -6
- package/src/db/Table.res.mjs +13 -4
- package/src/sources/BlockStore.res +7 -2
- package/src/sources/EvmHyperSyncSource.res +2 -0
- package/src/sources/EvmHyperSyncSource.res.mjs +2 -2
- package/src/sources/FuelHyperSyncSource.res +1 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +1 -1
- package/src/sources/HyperSync.res +4 -0
- package/src/sources/HyperSync.res.mjs +4 -2
- package/src/sources/HyperSync.resi +1 -0
- package/src/sources/HyperSyncClient.res +3 -0
- package/src/sources/HyperSyncSSE.res +1 -1
- package/src/sources/HyperSyncSSE.res.mjs +4 -10
- package/src/sources/RpcSource.res +1 -0
- package/src/sources/RpcSource.res.mjs +1 -1
- package/src/sources/SimulateSource.res +1 -0
- package/src/sources/SimulateSource.res.mjs +1 -1
- package/src/sources/Source.res +7 -0
- package/src/sources/SourceManager.res +4 -3
- package/src/sources/SourceManager.res.mjs +2 -2
- package/src/sources/SvmHyperSyncClient.res +5 -0
- package/src/sources/SvmHyperSyncSource.res +3 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +4 -2
package/src/db/Table.res
CHANGED
|
@@ -331,18 +331,31 @@ let encodeIdsToJson = (table, ids: array<EntityId.t>): JSON.t =>
|
|
|
331
331
|
|
|
332
332
|
// TODO: Test whether it should be passed via args and match the column type
|
|
333
333
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
334
|
+
// Resolved once per table, because a getWhere looks up every field it filters
|
|
335
|
+
// on and scanning the array made that cost grow with the entity's width.
|
|
336
|
+
let fieldsByApiName: table => dict<fieldOrDerived> = Utils.WeakMap.memoize(table => {
|
|
337
|
+
let byApiName = Dict.make()
|
|
338
|
+
table.fields->Array.forEach(field =>
|
|
339
|
+
byApiName->Dict.set(
|
|
340
|
+
switch field {
|
|
341
|
+
| Field(f) => f->getApiFieldName
|
|
342
|
+
| DerivedFrom({fieldName}) => fieldName
|
|
343
|
+
},
|
|
344
|
+
field,
|
|
345
|
+
)
|
|
340
346
|
)
|
|
347
|
+
byApiName
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
let getFieldByApiName = (table, apiFieldName) =>
|
|
351
|
+
table->fieldsByApiName->Utils.Dict.dangerouslyGetNonOption(apiFieldName)
|
|
341
352
|
|
|
342
353
|
// Both schema instances are created once per field: rescript-schema compiles
|
|
343
354
|
// and caches operations on the schema instance, so building S.array(fieldSchema)
|
|
344
355
|
// per query would recompile the serializer on every call.
|
|
345
356
|
type queryField = {
|
|
357
|
+
fieldType: fieldType,
|
|
358
|
+
isArray: bool,
|
|
346
359
|
fieldSchema: S.t<unknown>,
|
|
347
360
|
// Serializes the values array of an "in" filter
|
|
348
361
|
arrayFieldSchema: S.t<unknown>,
|
|
@@ -363,6 +376,8 @@ let queryFields: table => dict<queryField> = Utils.WeakMap.memoize(table => {
|
|
|
363
376
|
dict->Dict.set(
|
|
364
377
|
field->getApiFieldName,
|
|
365
378
|
{
|
|
379
|
+
fieldType: field.fieldType,
|
|
380
|
+
isArray: field.isArray,
|
|
366
381
|
fieldSchema: field.fieldSchema,
|
|
367
382
|
arrayFieldSchema: switch field.fieldType {
|
|
368
383
|
| Bytea => Utils.Schema.bytesArray->S.toUnknown
|
package/src/db/Table.res.mjs
CHANGED
|
@@ -296,12 +296,18 @@ function encodeIdsToJson(table, ids) {
|
|
|
296
296
|
return S$RescriptSchema.reverseConvertToJsonOrThrow(ids, idsArraySchema(table));
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
let fieldsByApiName = Utils.$$WeakMap.memoize(table => {
|
|
300
|
+
let byApiName = {};
|
|
301
|
+
table.fields.forEach(field => {
|
|
301
302
|
let tmp;
|
|
302
303
|
tmp = field.TAG === "Field" ? getApiFieldName(field._0) : field._0.fieldName;
|
|
303
|
-
|
|
304
|
+
byApiName[tmp] = field;
|
|
304
305
|
});
|
|
306
|
+
return byApiName;
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
function getFieldByApiName(table, apiFieldName) {
|
|
310
|
+
return fieldsByApiName(table)[apiFieldName];
|
|
305
311
|
}
|
|
306
312
|
|
|
307
313
|
let queryFields = Utils.$$WeakMap.memoize(table => {
|
|
@@ -315,6 +321,8 @@ let queryFields = Utils.$$WeakMap.memoize(table => {
|
|
|
315
321
|
let tmp;
|
|
316
322
|
tmp = typeof match !== "object" && match === "Bytea" ? Utils.Schema.bytesArray : S$RescriptSchema.array(field$1.fieldSchema);
|
|
317
323
|
dict[getApiFieldName(field$1)] = {
|
|
324
|
+
fieldType: field$1.fieldType,
|
|
325
|
+
isArray: field$1.isArray,
|
|
318
326
|
fieldSchema: field$1.fieldSchema,
|
|
319
327
|
arrayFieldSchema: tmp,
|
|
320
328
|
pgDbFieldName: getPgDbFieldName(field$1),
|
|
@@ -420,7 +428,7 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
|
|
|
420
428
|
}
|
|
421
429
|
}
|
|
422
430
|
};
|
|
423
|
-
let field =
|
|
431
|
+
let field = fieldsByApiName(table)[location];
|
|
424
432
|
let field$1;
|
|
425
433
|
if (field !== undefined) {
|
|
426
434
|
field$1 = field;
|
|
@@ -533,6 +541,7 @@ export {
|
|
|
533
541
|
getIdSchema,
|
|
534
542
|
idsArraySchema,
|
|
535
543
|
encodeIdsToJson,
|
|
544
|
+
fieldsByApiName,
|
|
536
545
|
getFieldByApiName,
|
|
537
546
|
queryFields,
|
|
538
547
|
makeRowsSchema,
|
|
@@ -142,8 +142,13 @@ external materialize: (
|
|
|
142
142
|
// Hash of a stored block, if the store still holds it.
|
|
143
143
|
@send external getHash: (t, int) => Null.t<string> = "getHash"
|
|
144
144
|
|
|
145
|
-
// Unix timestamp of a stored block - exactly that block,
|
|
146
|
-
|
|
145
|
+
// Unix timestamp of a stored block - exactly that block, except for an SVM slot
|
|
146
|
+
// that produced none: with `allowSkippedSlot` the last real slot below it
|
|
147
|
+
// answers instead, which is what chain time is at a skipped slot. Only set it
|
|
148
|
+
// where the query covered every slot in its range, or a slot that was never
|
|
149
|
+
// asked about reads as one the chain skipped.
|
|
150
|
+
@send
|
|
151
|
+
external getTimestamp: (t, int, ~allowSkippedSlot: bool) => Null.t<int> = "getTimestamp"
|
|
147
152
|
|
|
148
153
|
// Block numbers in `[fromBlock, belowBlock)` with a stored hash, ascending.
|
|
149
154
|
@send
|
|
@@ -84,6 +84,7 @@ let make = (
|
|
|
84
84
|
~fromBlock,
|
|
85
85
|
~toBlock,
|
|
86
86
|
~addressSet,
|
|
87
|
+
~includeAllBlocks,
|
|
87
88
|
~knownHeight,
|
|
88
89
|
~partitionId as _,
|
|
89
90
|
~selection: FetchState.selection,
|
|
@@ -104,6 +105,7 @@ let make = (
|
|
|
104
105
|
~registrationIndexes=selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
105
106
|
~addressSet,
|
|
106
107
|
~clientFilteredContracts=selection.clientFilteredContracts,
|
|
108
|
+
~includeAllBlocks,
|
|
107
109
|
) catch {
|
|
108
110
|
| HyperSync.GetLogs.Error(WrongInstance) =>
|
|
109
111
|
throw(Source.SourceBehindHead({blockNumber: fromBlock, requestStats: []}))
|
|
@@ -44,12 +44,12 @@ function make(param) {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
47
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, includeAllBlocks, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
48
48
|
let totalTimeRef = Performance.now();
|
|
49
49
|
let startFetchingBatchTimeRef = Performance.now();
|
|
50
50
|
let pageUnsafe;
|
|
51
51
|
try {
|
|
52
|
-
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts);
|
|
52
|
+
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts, includeAllBlocks);
|
|
53
53
|
} catch (raw_exn) {
|
|
54
54
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
55
55
|
if (exn.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
|
|
@@ -28,7 +28,7 @@ function make(param) {
|
|
|
28
28
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
29
29
|
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
|
|
30
30
|
}
|
|
31
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, param$
|
|
31
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, param, knownHeight, param$1, selection, param$2, retry, logger) => {
|
|
32
32
|
let totalTimeRef = Performance.now();
|
|
33
33
|
let startFetchingBatchTimeRef = Performance.now();
|
|
34
34
|
let pageUnsafe;
|
|
@@ -137,6 +137,7 @@ module GetLogs = {
|
|
|
137
137
|
~registrationIndexes,
|
|
138
138
|
~addressSet,
|
|
139
139
|
~clientFilteredContracts,
|
|
140
|
+
~includeAllBlocks,
|
|
140
141
|
): logsQueryPage => {
|
|
141
142
|
let query: HyperSyncClient.EventItems.query = {
|
|
142
143
|
fromBlock,
|
|
@@ -144,6 +145,9 @@ module GetLogs = {
|
|
|
144
145
|
?maxNumLogs,
|
|
145
146
|
registrationIndexes,
|
|
146
147
|
clientFilteredContracts,
|
|
148
|
+
// Absent rather than false, so a range that wants only the blocks its
|
|
149
|
+
// logs came from sends the query it always sent.
|
|
150
|
+
includeAllBlocks: ?(includeAllBlocks ? Some(true) : None),
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
let (res, transactionStore, blockStore) = switch await client.getEventItems(
|
|
@@ -137,13 +137,15 @@ function extractMissingParams(exn) {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes, addressSet, clientFilteredContracts) {
|
|
140
|
+
async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes, addressSet, clientFilteredContracts, includeAllBlocks) {
|
|
141
|
+
let query_includeAllBlocks = includeAllBlocks ? true : undefined;
|
|
141
142
|
let query$1 = {
|
|
142
143
|
fromBlock: fromBlock,
|
|
143
144
|
toBlock: toBlock,
|
|
144
145
|
maxNumLogs: maxNumLogs,
|
|
145
146
|
registrationIndexes: registrationIndexes,
|
|
146
|
-
clientFilteredContracts: clientFilteredContracts
|
|
147
|
+
clientFilteredContracts: clientFilteredContracts,
|
|
148
|
+
includeAllBlocks: query_includeAllBlocks
|
|
147
149
|
};
|
|
148
150
|
let match;
|
|
149
151
|
try {
|
|
@@ -262,6 +262,9 @@ module EventItems = {
|
|
|
262
262
|
// depend on addresses (client-side filtering). None/empty means
|
|
263
263
|
// every address-dependent contract is filtered server-side.
|
|
264
264
|
clientFilteredContracts: option<array<string>>,
|
|
265
|
+
// Return a header for every block in the range, not only the ones a log
|
|
266
|
+
// landed on. Absent means only the blocks logs came from.
|
|
267
|
+
includeAllBlocks?: bool,
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
type item = {
|
|
@@ -25,7 +25,7 @@ let subscribe = (~hyperSyncUrl, ~apiToken, ~onHeight, ~onStatus) =>
|
|
|
25
25
|
args.headers
|
|
26
26
|
->Option.getOr(Dict.make())
|
|
27
27
|
->Utils.Dict.merge(
|
|
28
|
-
|
|
28
|
+
dict{"Authorization": `Bearer ${apiToken}`, "User-Agent": userAgent},
|
|
29
29
|
)
|
|
30
30
|
EventSource.Fetch.fetch(url, ~args={...args, headers: headers})
|
|
31
31
|
},
|
|
@@ -35,16 +35,10 @@ function subscribe(hyperSyncUrl, apiToken, onHeight, onStatus) {
|
|
|
35
35
|
let userAgent = `hyperindex/` + Utils.EnvioPackage.value.version;
|
|
36
36
|
let es = new Eventsource.EventSource(hyperSyncUrl + `/height/sse`, {
|
|
37
37
|
fetch: (url, args) => {
|
|
38
|
-
let headers = Utils.Dict.merge(Stdlib_Option.getOr(args.headers, {}),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
],
|
|
43
|
-
[
|
|
44
|
-
"User-Agent",
|
|
45
|
-
userAgent
|
|
46
|
-
]
|
|
47
|
-
]));
|
|
38
|
+
let headers = Utils.Dict.merge(Stdlib_Option.getOr(args.headers, {}), {
|
|
39
|
+
Authorization: `Bearer ` + apiToken,
|
|
40
|
+
"User-Agent": userAgent
|
|
41
|
+
});
|
|
48
42
|
let newrecord = {...args};
|
|
49
43
|
return fetch(url, (newrecord.headers = headers, newrecord));
|
|
50
44
|
}
|
|
@@ -874,7 +874,7 @@ function make(param) {
|
|
|
874
874
|
Error: new Error()
|
|
875
875
|
};
|
|
876
876
|
}, lowercaseAddresses);
|
|
877
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, partitionId, selection, param, retry, param$
|
|
877
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, param, knownHeight, partitionId, selection, param$1, retry, param$2) => {
|
|
878
878
|
let startFetchingBatchTimeRef = Performance.now();
|
|
879
879
|
let toBlock$1 = toBlock !== undefined ? Primitive_int.min(toBlock, knownHeight) : knownHeight;
|
|
880
880
|
let firstBlockPromise = fromBlock > 0 && fromBlock <= toBlock$1 ? LazyLoader.get(blockLoader.contents, fromBlock).then(json => parseBlockInfo(json)) : Promise.resolve(undefined);
|
|
@@ -27,7 +27,7 @@ function make(items, endBlock, chainId, addressStore, ecosystemOpt, transactionS
|
|
|
27
27
|
height: reportedHeight,
|
|
28
28
|
requestStats: []
|
|
29
29
|
}),
|
|
30
|
-
getItemsOrThrow: (fromBlock, toBlock, addressSet, param, param$1, selection, param$
|
|
30
|
+
getItemsOrThrow: (fromBlock, toBlock, addressSet, param, param$1, param$2, selection, param$3, param$4, param$5) => {
|
|
31
31
|
let toBlockQueried = toBlock !== undefined ? toBlock : reportedHeight;
|
|
32
32
|
let selectionRegistrationIndexes = new Set();
|
|
33
33
|
selection.onEventRegistrations.forEach(reg => {
|
package/src/sources/Source.res
CHANGED
|
@@ -197,6 +197,13 @@ type t = {
|
|
|
197
197
|
// straight to its Rust client, which builds the query's address filter from
|
|
198
198
|
// it and gates every returned item against the chain-wide store.
|
|
199
199
|
~addressSet: AddressSet.t,
|
|
200
|
+
// Return a header for every block in the range, not only the ones an item
|
|
201
|
+
// landed on. The progress block's timestamp is what measures how far behind
|
|
202
|
+
// chain time the indexer is, and at the head that block often carries no
|
|
203
|
+
// item of its own. Only set once the chain is at the head, where the range
|
|
204
|
+
// is a handful of blocks; over a backfill range it would be a header per
|
|
205
|
+
// block for no gain.
|
|
206
|
+
~includeAllBlocks: bool,
|
|
200
207
|
~knownHeight: int,
|
|
201
208
|
~partitionId: string,
|
|
202
209
|
~selection: FetchState.selection,
|
|
@@ -705,7 +705,7 @@ let waitForNewBlock = (sourceManager: t, ~knownHeight, ~isRealtime, ~reducedPoll
|
|
|
705
705
|
logger->Logging.childTrace(
|
|
706
706
|
reducedPolling
|
|
707
707
|
? `Waiting for new blocks with reduced polling (${(sourceManager.reducedPollingInterval / 1000)
|
|
708
|
-
->Int.toString}s)
|
|
708
|
+
->Int.toString}s) until the indexer enters realtime mode.`
|
|
709
709
|
: "Initiating check for new blocks.",
|
|
710
710
|
)
|
|
711
711
|
sourceManager.waitingLogged = true
|
|
@@ -717,8 +717,8 @@ let waitForNewBlock = (sourceManager: t, ~knownHeight, ~isRealtime, ~reducedPoll
|
|
|
717
717
|
// cadence the sources poll at and the level the closing line is logged at.
|
|
718
718
|
let stalled = ref(false)
|
|
719
719
|
|
|
720
|
-
// Use a much longer stall timeout when reduced polling is active
|
|
721
|
-
//
|
|
720
|
+
// Use a much longer stall timeout when reduced polling is active, so a chain
|
|
721
|
+
// deliberately asking rarely doesn't report itself stalled between polls.
|
|
722
722
|
let stallTimeout = if reducedPolling {
|
|
723
723
|
sourceManager.reducedPollingInterval * 2
|
|
724
724
|
} else if isRealtime {
|
|
@@ -948,6 +948,7 @@ let executeQuery = async (
|
|
|
948
948
|
~fromBlock=query.fromBlock,
|
|
949
949
|
~toBlock,
|
|
950
950
|
~addressSet=query.addresses,
|
|
951
|
+
~includeAllBlocks=isRealtime,
|
|
951
952
|
~partitionId=query.partitionId,
|
|
952
953
|
~knownHeight,
|
|
953
954
|
~selection=query.selection->FetchState.narrowSelectionToRange(~toBlock),
|
|
@@ -537,7 +537,7 @@ function waitForNewBlock(sourceManager, knownHeight, isRealtime, reducedPolling)
|
|
|
537
537
|
knownHeight: knownHeight
|
|
538
538
|
});
|
|
539
539
|
if (!sourceManager.waitingLogged) {
|
|
540
|
-
Logging.childTrace(logger, reducedPolling ? `Waiting for new blocks with reduced polling (` + (sourceManager.reducedPollingInterval / 1000 | 0).toString() + `s)
|
|
540
|
+
Logging.childTrace(logger, reducedPolling ? `Waiting for new blocks with reduced polling (` + (sourceManager.reducedPollingInterval / 1000 | 0).toString() + `s) until the indexer enters realtime mode.` : "Initiating check for new blocks.");
|
|
541
541
|
sourceManager.waitingLogged = true;
|
|
542
542
|
}
|
|
543
543
|
let mainSources = getNextSources(sourceManager, isRealtime, undefined);
|
|
@@ -691,7 +691,7 @@ async function executeQuery(sourceManager, query, knownHeight, isRealtime) {
|
|
|
691
691
|
retry: retry
|
|
692
692
|
});
|
|
693
693
|
try {
|
|
694
|
-
let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addresses, knownHeight, query.partitionId, FetchState.narrowSelectionToRange(query.selection, toBlock), query.itemsTarget, retry, logger$2);
|
|
694
|
+
let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addresses, isRealtime, knownHeight, query.partitionId, FetchState.narrowSelectionToRange(query.selection, toBlock), query.itemsTarget, retry, logger$2);
|
|
695
695
|
recordStatsInto(sourceState.requestStats, response.requestStats);
|
|
696
696
|
validateResponseBlockStore("getItems", response.blockStore, undefined);
|
|
697
697
|
sourceState.lastFailedAt = undefined;
|
|
@@ -143,6 +143,11 @@ module EventItems = {
|
|
|
143
143
|
// depend on addresses (client-side filtering). None/empty means every
|
|
144
144
|
// address-dependent program is filtered server-side.
|
|
145
145
|
clientFilteredContracts: option<array<string>>,
|
|
146
|
+
// Return a block for every slot in the range, not only the ones an
|
|
147
|
+
// instruction landed on. Absent means only the slots instructions came
|
|
148
|
+
// from, which leaves a skipped slot indistinguishable from an unfetched
|
|
149
|
+
// one.
|
|
150
|
+
includeAllBlocks?: bool,
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
// NAPI encodes Rust `None` as `null`, never `undefined`, so an unselected
|
|
@@ -147,6 +147,7 @@ let make = (
|
|
|
147
147
|
~fromBlock,
|
|
148
148
|
~toBlock,
|
|
149
149
|
~addressSet,
|
|
150
|
+
~includeAllBlocks,
|
|
150
151
|
~knownHeight,
|
|
151
152
|
~partitionId as _,
|
|
152
153
|
~selection: FetchState.selection,
|
|
@@ -163,6 +164,8 @@ let make = (
|
|
|
163
164
|
maxNumInstructions: ?itemsTarget,
|
|
164
165
|
registrationIndexes: selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
165
166
|
clientFilteredContracts: selection.clientFilteredContracts,
|
|
167
|
+
// Absent rather than false, so a backfill query is the one it always was.
|
|
168
|
+
includeAllBlocks: ?(includeAllBlocks ? Some(true) : None),
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
let (resp, transactionStore, blockStore) = try await client.getEventItems(
|
|
@@ -106,17 +106,19 @@ function make(param) {
|
|
|
106
106
|
let chainId = param.chainId;
|
|
107
107
|
let apiToken = HyperSync.requireApiToken(param.apiToken);
|
|
108
108
|
let client = SvmHyperSyncClient.make(endpointUrl, apiToken, param.clientTimeoutMillis, undefined, undefined, SvmHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), param.addressStore);
|
|
109
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
109
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, includeAllBlocks, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
110
110
|
let totalTimeRef = Performance.now();
|
|
111
111
|
let pageFetchRef = Performance.now();
|
|
112
112
|
let query_registrationIndexes = selection.onEventRegistrations.map(reg => reg.index);
|
|
113
113
|
let query_clientFilteredContracts = selection.clientFilteredContracts;
|
|
114
|
+
let query_includeAllBlocks = includeAllBlocks ? true : undefined;
|
|
114
115
|
let query = {
|
|
115
116
|
fromSlot: fromBlock,
|
|
116
117
|
toSlot: toBlock,
|
|
117
118
|
maxNumInstructions: itemsTarget,
|
|
118
119
|
registrationIndexes: query_registrationIndexes,
|
|
119
|
-
clientFilteredContracts: query_clientFilteredContracts
|
|
120
|
+
clientFilteredContracts: query_clientFilteredContracts,
|
|
121
|
+
includeAllBlocks: query_includeAllBlocks
|
|
120
122
|
};
|
|
121
123
|
let match;
|
|
122
124
|
try {
|