envio 3.11.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/index.d.ts +3 -0
- package/package.json +6 -6
- package/src/Batch.res +111 -78
- package/src/Batch.res.mjs +53 -46
- package/src/BatchProcessing.res +1 -11
- package/src/BatchProcessing.res.mjs +1 -4
- package/src/ChainFetching.res +7 -3
- package/src/ChainFetching.res.mjs +1 -1
- package/src/ChainState.res +82 -20
- package/src/ChainState.res.mjs +51 -13
- package/src/ChainState.resi +6 -1
- package/src/Config.res +58 -37
- package/src/Config.res.mjs +63 -53
- package/src/CrossChainState.res +50 -53
- package/src/CrossChainState.res.mjs +25 -23
- package/src/CrossChainState.resi +6 -13
- package/src/EffectState.res +13 -4
- package/src/EffectState.resi +7 -1
- package/src/EventProcessing.res +6 -6
- package/src/EventProcessing.res.mjs +6 -6
- package/src/FetchState.res +65 -46
- package/src/FetchState.res.mjs +68 -36
- package/src/FinalizeBackfill.res +16 -12
- package/src/FinalizeBackfill.res.mjs +3 -3
- package/src/HistoryPolicy.res +46 -0
- package/src/HistoryPolicy.res.mjs +50 -0
- package/src/InMemoryStore.res +30 -32
- package/src/InMemoryStore.res.mjs +33 -28
- package/src/InMemoryTable.res +155 -67
- package/src/InMemoryTable.res.mjs +151 -60
- package/src/IndexerState.res +66 -45
- package/src/IndexerState.res.mjs +57 -29
- package/src/IndexerState.resi +8 -13
- package/src/Internal.res +4 -2
- package/src/LoadLayer.res +68 -38
- package/src/LoadLayer.res.mjs +50 -64
- package/src/LoadLayer.resi +1 -1
- package/src/Main.res +25 -24
- package/src/Main.res.mjs +24 -25
- package/src/Metrics.res +49 -1
- package/src/Metrics.res.mjs +26 -3
- package/src/Persistence.res +55 -16
- package/src/Persistence.res.mjs +18 -3
- package/src/PgStorage.res +286 -180
- package/src/PgStorage.res.mjs +209 -122
- package/src/PruneStaleHistory.res +9 -15
- package/src/PruneStaleHistory.res.mjs +11 -20
- package/src/Rollback.res +9 -14
- package/src/Rollback.res.mjs +5 -3
- package/src/Sink.res +7 -5
- package/src/Sink.res.mjs +4 -4
- package/src/Staging.res +298 -0
- package/src/Staging.res.mjs +257 -0
- package/src/TestIndexer.res +14 -30
- package/src/TestIndexer.res.mjs +11 -9
- package/src/UserContext.res +20 -36
- package/src/UserContext.res.mjs +6 -9
- package/src/Utils.res +10 -4
- package/src/Utils.res.mjs +16 -16
- package/src/Writing.res +34 -20
- package/src/Writing.res.mjs +15 -20
- package/src/bindings/ClickHouse.res +41 -34
- package/src/bindings/ClickHouse.res.mjs +36 -30
- package/src/bindings/ClickHouseSink.res +45 -186
- package/src/bindings/ClickHouseSink.res.mjs +21 -174
- package/src/db/CheckpointSequence.res +109 -0
- package/src/db/CheckpointSequence.res.mjs +99 -0
- package/src/db/EntityFilter.res +487 -275
- package/src/db/EntityFilter.res.mjs +557 -309
- package/src/db/EntityHistory.res +6 -5
- package/src/db/EntityHistory.res.mjs +5 -5
- package/src/db/Frontier.res +86 -0
- package/src/db/Frontier.res.mjs +126 -0
- package/src/db/InternalTable.res +145 -27
- package/src/db/InternalTable.res.mjs +115 -29
- package/src/db/RollbackFloors.res +34 -41
- package/src/db/RollbackFloors.res.mjs +27 -71
- package/src/db/Table.res +21 -6
- package/src/db/Table.res.mjs +13 -4
- package/src/sources/BlockStore.res +8 -0
- package/src/sources/EvmHyperSyncSource.res +5 -1
- package/src/sources/EvmHyperSyncSource.res.mjs +4 -3
- package/src/sources/FuelHyperSyncSource.res +1 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +1 -1
- package/src/sources/HyperSync.res +6 -0
- package/src/sources/HyperSync.res.mjs +5 -2
- package/src/sources/HyperSync.resi +2 -0
- package/src/sources/HyperSyncClient.res +6 -0
- package/src/sources/HyperSyncSSE.res +1 -1
- package/src/sources/HyperSyncSSE.res.mjs +4 -10
- package/src/sources/RequestStat.res +8 -1
- 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 +11 -3
- package/src/sources/SourceManager.res +34 -13
- package/src/sources/SourceManager.res.mjs +26 -9
- package/src/sources/SourceManager.resi +2 -0
- package/src/sources/SvmHyperSyncClient.res +5 -0
- package/src/sources/SvmHyperSyncSource.res +3 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +4 -2
- package/src/tui/Tui.res +56 -143
- package/src/tui/Tui.res.mjs +70 -166
- package/src/tui/components/TuiData.res +61 -16
- package/src/tui/components/TuiData.res.mjs +53 -15
- package/svm.schema.json +0 -7
- package/src/db/CheckpointBounds.res +0 -53
- package/src/db/CheckpointBounds.res.mjs +0 -44
|
@@ -5,13 +5,16 @@ import * as Utils from "../Utils.res.mjs";
|
|
|
5
5
|
import * as Config from "../Config.res.mjs";
|
|
6
6
|
import * as Address from "../Address.res.mjs";
|
|
7
7
|
import * as ChainId from "../ChainId.res.mjs";
|
|
8
|
+
import * as Frontier from "./Frontier.res.mjs";
|
|
9
|
+
import * as Internal from "../Internal.res.mjs";
|
|
8
10
|
import * as Postgres from "../bindings/Postgres.res.mjs";
|
|
9
11
|
import * as AddressRows from "../AddressRows.res.mjs";
|
|
10
12
|
import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
|
|
11
13
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
12
14
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
13
|
-
import * as
|
|
15
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
14
16
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
17
|
+
import * as CheckpointSequence from "./CheckpointSequence.res.mjs";
|
|
15
18
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
16
19
|
|
|
17
20
|
let undefinedTableSqlState = "42P01";
|
|
@@ -158,9 +161,11 @@ let fields = [
|
|
|
158
161
|
"first_event_block",
|
|
159
162
|
"buffer_block",
|
|
160
163
|
"progress_block",
|
|
164
|
+
"progress_block_time",
|
|
161
165
|
"ready_at",
|
|
162
166
|
"events_processed",
|
|
163
|
-
"_is_hyper_sync"
|
|
167
|
+
"_is_hyper_sync",
|
|
168
|
+
"checkpoint_id"
|
|
164
169
|
];
|
|
165
170
|
|
|
166
171
|
let table$2 = Table.mkTable("envio_chains", undefined, [
|
|
@@ -175,7 +180,9 @@ let table$2 = Table.mkTable("envio_chains", undefined, [
|
|
|
175
180
|
Table.mkField("ready_at", "Date", S$RescriptSchema.$$null(Utils.Schema.dbDate), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
176
181
|
Table.mkField("events_processed", "UInt52", S$RescriptSchema.float, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
177
182
|
Table.mkField("_is_hyper_sync", "Boolean", S$RescriptSchema.bool, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
178
|
-
Table.mkField("progress_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
183
|
+
Table.mkField("progress_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
184
|
+
Table.mkField("progress_block_time", "Date", S$RescriptSchema.$$null(Utils.Schema.dbDate), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
185
|
+
Table.mkField("checkpoint_id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
179
186
|
], undefined);
|
|
180
187
|
|
|
181
188
|
function initialFromConfig(chainConfig) {
|
|
@@ -187,7 +194,9 @@ function initialFromConfig(chainConfig) {
|
|
|
187
194
|
max_reorg_depth: chainConfig.maxReorgDepth,
|
|
188
195
|
source_block: 0,
|
|
189
196
|
progress_block: -1,
|
|
197
|
+
progress_block_time: null,
|
|
190
198
|
events_processed: 0,
|
|
199
|
+
checkpoint_id: Internal.initialCheckpointId,
|
|
191
200
|
first_event_block: null,
|
|
192
201
|
buffer_block: -1,
|
|
193
202
|
ready_at: null,
|
|
@@ -260,7 +269,9 @@ function makeGetInitialStateQuery(pgSchema) {
|
|
|
260
269
|
"` + "ready_at" + `" as "timestampCaughtUpToHeadOrEndblock",
|
|
261
270
|
"` + "events_processed" + `"::float8 as "numEventsProcessed",
|
|
262
271
|
"` + "progress_block" + `" as "progressBlockNumber",
|
|
263
|
-
"` + "
|
|
272
|
+
"` + "progress_block_time" + `" as "progressBlockTime",
|
|
273
|
+
"` + "source_block" + `" as "sourceBlockNumber",
|
|
274
|
+
"` + "checkpoint_id" + `"::TEXT as "checkpointId"
|
|
264
275
|
FROM "` + pgSchema + `"."` + table$2.tableName + `";`;
|
|
265
276
|
}
|
|
266
277
|
|
|
@@ -281,14 +292,25 @@ async function getInitialState(sql, pgSchema) {
|
|
|
281
292
|
timestampCaughtUpToHeadOrEndblock: rawInitialState.timestampCaughtUpToHeadOrEndblock,
|
|
282
293
|
numEventsProcessed: rawInitialState.numEventsProcessed,
|
|
283
294
|
progressBlockNumber: rawInitialState.progressBlockNumber,
|
|
295
|
+
progressBlockTime: rawInitialState.progressBlockTime,
|
|
284
296
|
addressRows: Stdlib_Option.getOr(addressRowsByChainId[ChainId.toString(id)], AddressRows.emptySeedRows()),
|
|
285
|
-
sourceBlockNumber: rawInitialState.sourceBlockNumber
|
|
297
|
+
sourceBlockNumber: rawInitialState.sourceBlockNumber,
|
|
298
|
+
checkpointId: rawInitialState.checkpointId
|
|
286
299
|
};
|
|
287
300
|
});
|
|
288
301
|
}
|
|
289
302
|
|
|
303
|
+
function blockTimeToDb(blockTime) {
|
|
304
|
+
return Stdlib_Null.fromOption(Stdlib_Option.map(blockTime, seconds => new Date(seconds * 1000)));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function blockTimeFromDb(date) {
|
|
308
|
+
return Stdlib_Option.map(date === null ? undefined : Primitive_option.some(date), date => date.getTime() / 1000 | 0);
|
|
309
|
+
}
|
|
310
|
+
|
|
290
311
|
let progressFields = [
|
|
291
312
|
"progress_block",
|
|
313
|
+
"progress_block_time",
|
|
292
314
|
"events_processed",
|
|
293
315
|
"source_block"
|
|
294
316
|
];
|
|
@@ -325,8 +347,10 @@ function setProgressedChains(sql, pgSchema, progressedChains) {
|
|
|
325
347
|
let params = [];
|
|
326
348
|
params.push(data.chainId);
|
|
327
349
|
progressFields.forEach(field => {
|
|
328
|
-
params.push(field === "
|
|
329
|
-
field === "
|
|
350
|
+
params.push(field === "progress_block_time" ? blockTimeToDb(data.progressBlockTime) : (
|
|
351
|
+
field === "source_block" ? data.sourceBlockNumber : (
|
|
352
|
+
field === "progress_block" ? data.progressBlockNumber : data.totalEventsProcessed
|
|
353
|
+
)
|
|
330
354
|
));
|
|
331
355
|
});
|
|
332
356
|
promises.push(sql.unsafe(query, params, {prepare: true}));
|
|
@@ -334,6 +358,20 @@ function setProgressedChains(sql, pgSchema, progressedChains) {
|
|
|
334
358
|
return Promise.all(promises);
|
|
335
359
|
}
|
|
336
360
|
|
|
361
|
+
function makeSetCheckpointFrontierQuery(pgSchema, chainIdModeOpt) {
|
|
362
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
363
|
+
let chainIdArrayType$1 = chainIdArrayType(pgSchema, chainIdMode);
|
|
364
|
+
return `UPDATE "` + pgSchema + `"."` + table$2.tableName + `"
|
|
365
|
+
SET "` + "checkpoint_id" + `" = envio_frontier.checkpoint_id
|
|
366
|
+
FROM unnest($1::` + chainIdArrayType$1 + `,$2::` + "BIGINT" + `[]) AS envio_frontier(chain_id, checkpoint_id)
|
|
367
|
+
WHERE "` + table$2.tableName + `"."` + "id" + `" = envio_frontier.chain_id;`;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function setCheckpointFrontier(sql, pgSchema, frontier, chainIdModeOpt) {
|
|
371
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
372
|
+
return sql.unsafe(makeSetCheckpointFrontierQuery(pgSchema, chainIdMode), Frontier.unnestParams(frontier), {prepare: true});
|
|
373
|
+
}
|
|
374
|
+
|
|
337
375
|
let Chains = {
|
|
338
376
|
fields: fields,
|
|
339
377
|
table: table$2,
|
|
@@ -344,10 +382,14 @@ let Chains = {
|
|
|
344
382
|
makeSetReadyAtQuery: makeSetReadyAtQuery,
|
|
345
383
|
makeGetInitialStateQuery: makeGetInitialStateQuery,
|
|
346
384
|
getInitialState: getInitialState,
|
|
385
|
+
blockTimeToDb: blockTimeToDb,
|
|
386
|
+
blockTimeFromDb: blockTimeFromDb,
|
|
347
387
|
progressFields: progressFields,
|
|
348
388
|
makeProgressFieldsUpdateQuery: makeProgressFieldsUpdateQuery,
|
|
349
389
|
setMeta: setMeta,
|
|
350
|
-
setProgressedChains: setProgressedChains
|
|
390
|
+
setProgressedChains: setProgressedChains,
|
|
391
|
+
makeSetCheckpointFrontierQuery: makeSetCheckpointFrontierQuery,
|
|
392
|
+
setCheckpointFrontier: setCheckpointFrontier
|
|
351
393
|
};
|
|
352
394
|
|
|
353
395
|
let table$3 = Table.mkTable("envio_info", undefined, [
|
|
@@ -393,33 +435,78 @@ let dbSchema = S$RescriptSchema.object(s => ({
|
|
|
393
435
|
|
|
394
436
|
let columns = [
|
|
395
437
|
{
|
|
396
|
-
field: Table.mkField("
|
|
397
|
-
clickHouseFieldType: "
|
|
398
|
-
valuesOf: batch => batch.
|
|
438
|
+
field: Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
439
|
+
clickHouseFieldType: "ChainId",
|
|
440
|
+
valuesOf: batch => batch.checkpointChainIds,
|
|
441
|
+
diffValuesOf: diffs => diffs.map(diff => diff.chainId)
|
|
399
442
|
},
|
|
400
443
|
{
|
|
401
|
-
field: Table.mkField("
|
|
402
|
-
clickHouseFieldType: "
|
|
403
|
-
valuesOf: batch => batch.
|
|
444
|
+
field: Table.mkField("id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
445
|
+
clickHouseFieldType: "UInt64",
|
|
446
|
+
valuesOf: batch => batch.checkpointIds,
|
|
447
|
+
diffValuesOf: diffs => diffs.map(diff => diff.checkpointId)
|
|
404
448
|
},
|
|
405
449
|
{
|
|
406
450
|
field: Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
407
451
|
clickHouseFieldType: "Int32",
|
|
408
|
-
valuesOf: batch => batch.checkpointBlockNumbers
|
|
452
|
+
valuesOf: batch => batch.checkpointBlockNumbers,
|
|
453
|
+
diffValuesOf: diffs => diffs.map(diff => diff.blockNumber)
|
|
409
454
|
},
|
|
410
455
|
{
|
|
411
456
|
field: Table.mkField("block_hash", "String", S$RescriptSchema.$$null(S$RescriptSchema.string), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
412
457
|
clickHouseFieldType: "String",
|
|
413
|
-
valuesOf: batch => batch.checkpointBlockHashes
|
|
458
|
+
valuesOf: batch => batch.checkpointBlockHashes,
|
|
459
|
+
diffValuesOf: diffs => diffs.map(param => null)
|
|
414
460
|
},
|
|
415
461
|
{
|
|
416
462
|
field: Table.mkField("events_processed", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
417
463
|
clickHouseFieldType: "UInt64",
|
|
418
|
-
valuesOf: batch => batch.checkpointEventsProcessed
|
|
464
|
+
valuesOf: batch => batch.checkpointEventsProcessed,
|
|
465
|
+
diffValuesOf: diffs => diffs.map(param => 0)
|
|
419
466
|
}
|
|
420
467
|
];
|
|
421
468
|
|
|
422
|
-
let
|
|
469
|
+
let tableName = "envio_checkpoints";
|
|
470
|
+
|
|
471
|
+
let table$4 = Table.mkTable(tableName, undefined, columns.map(param => param.field), undefined);
|
|
472
|
+
|
|
473
|
+
let globalTable = Table.mkTable(tableName, undefined, columns.map(param => {
|
|
474
|
+
let column = param.field;
|
|
475
|
+
if (column.TAG !== "Field") {
|
|
476
|
+
return column;
|
|
477
|
+
}
|
|
478
|
+
let f = column._0;
|
|
479
|
+
if (f.fieldName === "chain_id") {
|
|
480
|
+
return {
|
|
481
|
+
TAG: "Field",
|
|
482
|
+
_0: {
|
|
483
|
+
fieldName: f.fieldName,
|
|
484
|
+
fieldType: f.fieldType,
|
|
485
|
+
fieldSchema: f.fieldSchema,
|
|
486
|
+
isArray: f.isArray,
|
|
487
|
+
isNullable: f.isNullable,
|
|
488
|
+
isPrimaryKey: false,
|
|
489
|
+
isIndex: f.isIndex,
|
|
490
|
+
isChainId: f.isChainId,
|
|
491
|
+
linkedEntity: f.linkedEntity,
|
|
492
|
+
defaultValue: f.defaultValue,
|
|
493
|
+
description: f.description,
|
|
494
|
+
postgresDbName: f.postgresDbName,
|
|
495
|
+
clickhouseDbName: f.clickhouseDbName
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
} else {
|
|
499
|
+
return column;
|
|
500
|
+
}
|
|
501
|
+
}), undefined);
|
|
502
|
+
|
|
503
|
+
function tableFor(sequence) {
|
|
504
|
+
if (sequence === "SharedAcrossChains") {
|
|
505
|
+
return globalTable;
|
|
506
|
+
} else {
|
|
507
|
+
return table$4;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
423
510
|
|
|
424
511
|
function makeGetReorgCheckpointsQuery(pgSchema) {
|
|
425
512
|
return `WITH reorg_chains AS (
|
|
@@ -443,10 +530,6 @@ WHERE cp."` + "block_hash" + `" IS NOT NULL
|
|
|
443
530
|
ORDER BY cp."` + "id" + `";`;
|
|
444
531
|
}
|
|
445
532
|
|
|
446
|
-
function makeCommitedCheckpointIdQuery(pgSchema) {
|
|
447
|
-
return `SELECT COALESCE(MAX(` + "id" + `), ` + (0n).toString() + `) AS id FROM "` + pgSchema + `"."` + table$4.tableName + `";`;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
533
|
function makeInsertCheckpointQuery(pgSchema, chainIdModeOpt) {
|
|
451
534
|
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
452
535
|
let chainIdArrayType$1 = chainIdArrayType(pgSchema, chainIdMode);
|
|
@@ -471,18 +554,18 @@ let chainIdColumn = "chain_id";
|
|
|
471
554
|
|
|
472
555
|
function rollback(sql, pgSchema, floors) {
|
|
473
556
|
let tableRef = `"` + pgSchema + `"."` + table$4.tableName + `"`;
|
|
474
|
-
let bounds =
|
|
475
|
-
return sql.unsafe(`DELETE FROM ` + tableRef + bounds.using + ` WHERE "` + "id" + `" > ` + bounds.checkpointId + bounds.usingMatch + `;`,
|
|
557
|
+
let bounds = CheckpointSequence.sql(floors.checkpointBounds, chainIdColumn, tableRef);
|
|
558
|
+
return sql.unsafe(`DELETE FROM ` + tableRef + bounds.using + ` WHERE "` + "id" + `" > ` + bounds.checkpointId + bounds.usingMatch + `;`, CheckpointSequence.params(floors.checkpointBounds), {prepare: true});
|
|
476
559
|
}
|
|
477
560
|
|
|
478
561
|
function makePruneStaleCheckpointsQuery(pgSchema, safeCheckpoints) {
|
|
479
562
|
let tableRef = `"` + pgSchema + `"."` + table$4.tableName + `"`;
|
|
480
|
-
let bounds =
|
|
563
|
+
let bounds = CheckpointSequence.sql(safeCheckpoints, chainIdColumn, tableRef);
|
|
481
564
|
return `DELETE FROM ` + tableRef + bounds.using + ` WHERE "` + "id" + `" < ` + bounds.checkpointId + bounds.usingMatch + `;`;
|
|
482
565
|
}
|
|
483
566
|
|
|
484
567
|
function pruneStaleCheckpoints(sql, pgSchema, safeCheckpoints) {
|
|
485
|
-
return sql.unsafe(makePruneStaleCheckpointsQuery(pgSchema, safeCheckpoints),
|
|
568
|
+
return sql.unsafe(makePruneStaleCheckpointsQuery(pgSchema, safeCheckpoints), CheckpointSequence.params(safeCheckpoints), {prepare: true});
|
|
486
569
|
}
|
|
487
570
|
|
|
488
571
|
function makeGetRollbackTargetCheckpointQuery(pgSchema) {
|
|
@@ -503,7 +586,7 @@ function getRollbackTargetCheckpoint(sql, pgSchema, reorgChainId, lastKnownValid
|
|
|
503
586
|
}
|
|
504
587
|
|
|
505
588
|
function makeGetRollbackProgressDiffQuery(pgSchema, floors) {
|
|
506
|
-
let bounds =
|
|
589
|
+
let bounds = CheckpointSequence.sql(floors.checkpointBounds, chainIdColumn, "t");
|
|
507
590
|
return `SELECT
|
|
508
591
|
t."` + "chain_id" + `"::float8 as "` + "chain_id" + `",
|
|
509
592
|
SUM(t."` + "events_processed" + `") as events_processed_diff,
|
|
@@ -514,16 +597,18 @@ GROUP BY t."` + "chain_id" + `";`;
|
|
|
514
597
|
}
|
|
515
598
|
|
|
516
599
|
function getRollbackProgressDiff(sql, pgSchema, floors) {
|
|
517
|
-
return sql.unsafe(makeGetRollbackProgressDiffQuery(pgSchema, floors),
|
|
600
|
+
return sql.unsafe(makeGetRollbackProgressDiffQuery(pgSchema, floors), CheckpointSequence.params(floors.checkpointBounds), {prepare: true});
|
|
518
601
|
}
|
|
519
602
|
|
|
520
603
|
let Checkpoints = {
|
|
521
604
|
dbSchema: dbSchema,
|
|
522
605
|
initialCheckpointId: 0n,
|
|
523
606
|
columns: columns,
|
|
607
|
+
tableName: tableName,
|
|
524
608
|
table: table$4,
|
|
609
|
+
globalTable: globalTable,
|
|
610
|
+
tableFor: tableFor,
|
|
525
611
|
makeGetReorgCheckpointsQuery: makeGetReorgCheckpointsQuery,
|
|
526
|
-
makeCommitedCheckpointIdQuery: makeCommitedCheckpointIdQuery,
|
|
527
612
|
makeInsertCheckpointQuery: makeInsertCheckpointQuery,
|
|
528
613
|
insert: insert$2,
|
|
529
614
|
chainIdColumn: chainIdColumn,
|
|
@@ -584,6 +669,7 @@ SELECT
|
|
|
584
669
|
"` + "start_block" + `" AS "startBlock",
|
|
585
670
|
"` + "end_block" + `" AS "endBlock",
|
|
586
671
|
"` + "progress_block" + `" AS "progressBlock",
|
|
672
|
+
"` + "progress_block_time" + `" AS "progressBlockTime",
|
|
587
673
|
"` + "buffer_block" + `" AS "bufferBlock",
|
|
588
674
|
"` + "first_event_block" + `" AS "firstEventBlock",
|
|
589
675
|
"` + "events_processed" + `"::float4 AS "eventsProcessed",
|
|
@@ -1,55 +1,48 @@
|
|
|
1
|
-
// How far back a reorg rollback takes each chain: the last checkpoint each
|
|
2
|
-
// and for a chain whose own reorg set its floor, the last block that
|
|
3
|
-
// valid. Superseding an unwritten rollback with a new one is a
|
|
4
|
-
// minimum, so a merge can neither lose a chain's floor nor raise it.
|
|
1
|
+
// How far back a reorg rollback takes each chain: the last checkpoint each
|
|
2
|
+
// keeps, and for a chain whose own reorg set its floor, the last block that
|
|
3
|
+
// reorg left valid. Superseding an unwritten rollback with a new one is a
|
|
4
|
+
// pointwise minimum, so a merge can neither lose a chain's floor nor raise it.
|
|
5
5
|
type t = {
|
|
6
|
-
|
|
6
|
+
checkpointBounds: CheckpointSequence.checkpointBoundsByChain,
|
|
7
7
|
// Progress recomputed from the surviving checkpoints alone can land above the
|
|
8
8
|
// fork: the blocks between it and the chain's next checkpoint carried no
|
|
9
9
|
// events on the orphaned chain, but the chain replacing it can have its own.
|
|
10
10
|
// Absent for a chain dragged along by another chain's reorg.
|
|
11
|
-
forkBlockNumberByChain:
|
|
11
|
+
forkBlockNumberByChain: dict<int>,
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
merged->Array.setUnsafe(idx, (chainId, Pervasives.min(pendingValue, value)))
|
|
34
|
-
| None => merged->Array.push((chainId, value))
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
merged
|
|
14
|
+
// Under one shared sequence a reorg on any chain can have changed any chain's
|
|
15
|
+
// rows, so every chain goes back to the same checkpoint; with a counter per
|
|
16
|
+
// chain the floor names the reorg chain alone and every sibling is left alone.
|
|
17
|
+
let make = (
|
|
18
|
+
~sequence: CheckpointSequence.t,
|
|
19
|
+
~chainIds: array<ChainId.t>,
|
|
20
|
+
~reorgChainId,
|
|
21
|
+
~floorCheckpointId,
|
|
22
|
+
~forkBlockNumber,
|
|
23
|
+
) => {
|
|
24
|
+
checkpointBounds: {
|
|
25
|
+
CheckpointSequence.sequence,
|
|
26
|
+
byChain: switch sequence {
|
|
27
|
+
| SharedAcrossChains =>
|
|
28
|
+
chainIds->Array.map(chainId => (chainId, floorCheckpointId))->Frontier.fromEntries
|
|
29
|
+
| PerChain => Frontier.fromEntries([(reorgChainId, floorCheckpointId)])
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
forkBlockNumberByChain: Dict.fromArray([(reorgChainId->ChainId.toString, forkBlockNumber)]),
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
let merge = (pending: t, next: t) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
| (EveryChain(_), PerChain(_)) | (PerChain(_), EveryChain(_)) =>
|
|
45
|
-
JsError.throwWithMessage(
|
|
46
|
-
"Internal error: a rollback reaching every chain can't be merged with one isolated to a chain. The schema decides which a run builds, and it doesn't change.",
|
|
47
|
-
)
|
|
36
|
+
checkpointBounds: {
|
|
37
|
+
CheckpointSequence.sequence: next.checkpointBounds.sequence,
|
|
38
|
+
byChain: Frontier.mergeMin(pending.checkpointBounds.byChain, next.checkpointBounds.byChain),
|
|
48
39
|
},
|
|
49
|
-
forkBlockNumberByChain:
|
|
40
|
+
forkBlockNumberByChain: Utils.Dict.mergeWith(
|
|
41
|
+
pending.forkBlockNumberByChain,
|
|
42
|
+
next.forkBlockNumberByChain,
|
|
43
|
+
Pervasives.min,
|
|
44
|
+
),
|
|
50
45
|
}
|
|
51
46
|
|
|
52
47
|
let forkBlockNumber = (floors: t, chainId) =>
|
|
53
|
-
floors.forkBlockNumberByChain
|
|
54
|
-
->Array.find(((forkChainId, _)) => forkChainId === chainId)
|
|
55
|
-
->Option.map(((_, forkBlockNumber)) => forkBlockNumber)
|
|
48
|
+
floors.forkBlockNumberByChain->ChainId.Dict.dangerouslyGetNonOption(chainId)
|
|
@@ -1,92 +1,48 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
7
|
-
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
3
|
+
import * as Utils from "../Utils.res.mjs";
|
|
4
|
+
import * as ChainId from "../ChainId.res.mjs";
|
|
5
|
+
import * as Frontier from "./Frontier.res.mjs";
|
|
6
|
+
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
8
7
|
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
forkBlockNumberByChain: [[
|
|
19
|
-
chainId,
|
|
20
|
-
forkBlockNumber
|
|
21
|
-
]]
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function global(floorCheckpointId, reorgChainId, forkBlockNumber) {
|
|
8
|
+
function make(sequence, chainIds, reorgChainId, floorCheckpointId, forkBlockNumber) {
|
|
9
|
+
let tmp;
|
|
10
|
+
tmp = sequence === "SharedAcrossChains" ? Frontier.fromEntries(chainIds.map(chainId => [
|
|
11
|
+
chainId,
|
|
12
|
+
floorCheckpointId
|
|
13
|
+
])) : Frontier.fromEntries([[
|
|
14
|
+
reorgChainId,
|
|
15
|
+
floorCheckpointId
|
|
16
|
+
]]);
|
|
26
17
|
return {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
checkpointBounds: {
|
|
19
|
+
sequence: sequence,
|
|
20
|
+
byChain: tmp
|
|
30
21
|
},
|
|
31
|
-
forkBlockNumberByChain: [[
|
|
32
|
-
reorgChainId,
|
|
22
|
+
forkBlockNumberByChain: Object.fromEntries([[
|
|
23
|
+
ChainId.toString(reorgChainId),
|
|
33
24
|
forkBlockNumber
|
|
34
|
-
]]
|
|
25
|
+
]])
|
|
35
26
|
};
|
|
36
27
|
}
|
|
37
28
|
|
|
38
|
-
function mergeByChain(pending, next) {
|
|
39
|
-
let merged = pending.slice();
|
|
40
|
-
next.forEach(param => {
|
|
41
|
-
let value = param[1];
|
|
42
|
-
let chainId = param[0];
|
|
43
|
-
let idx = Stdlib_Array.findIndexOpt(merged, param => param[0] === chainId);
|
|
44
|
-
if (idx !== undefined) {
|
|
45
|
-
let match = merged[idx];
|
|
46
|
-
merged[idx] = [
|
|
47
|
-
chainId,
|
|
48
|
-
Primitive_object.min(match[1], value)
|
|
49
|
-
];
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
merged.push([
|
|
53
|
-
chainId,
|
|
54
|
-
value
|
|
55
|
-
]);
|
|
56
|
-
});
|
|
57
|
-
return merged;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
29
|
function merge(pending, next) {
|
|
61
|
-
let match = pending.floors;
|
|
62
|
-
let match$1 = next.floors;
|
|
63
|
-
let tmp;
|
|
64
|
-
tmp = match.TAG === "EveryChain" ? (
|
|
65
|
-
match$1.TAG === "EveryChain" ? ({
|
|
66
|
-
TAG: "EveryChain",
|
|
67
|
-
_0: Primitive_bigint.min(match._0, match$1._0)
|
|
68
|
-
}) : Stdlib_JsError.throwWithMessage("Internal error: a rollback reaching every chain can't be merged with one isolated to a chain. The schema decides which a run builds, and it doesn't change.")
|
|
69
|
-
) : (
|
|
70
|
-
match$1.TAG === "EveryChain" ? Stdlib_JsError.throwWithMessage("Internal error: a rollback reaching every chain can't be merged with one isolated to a chain. The schema decides which a run builds, and it doesn't change.") : ({
|
|
71
|
-
TAG: "PerChain",
|
|
72
|
-
_0: mergeByChain(match._0, match$1._0)
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
30
|
return {
|
|
76
|
-
|
|
77
|
-
|
|
31
|
+
checkpointBounds: {
|
|
32
|
+
sequence: next.checkpointBounds.sequence,
|
|
33
|
+
byChain: Frontier.mergeMin(pending.checkpointBounds.byChain, next.checkpointBounds.byChain)
|
|
34
|
+
},
|
|
35
|
+
forkBlockNumberByChain: Utils.Dict.mergeWith(pending.forkBlockNumberByChain, next.forkBlockNumberByChain, Primitive_int.min)
|
|
78
36
|
};
|
|
79
37
|
}
|
|
80
38
|
|
|
81
39
|
function forkBlockNumber(floors, chainId) {
|
|
82
|
-
return
|
|
40
|
+
return floors.forkBlockNumberByChain[chainId];
|
|
83
41
|
}
|
|
84
42
|
|
|
85
43
|
export {
|
|
86
|
-
|
|
87
|
-
global,
|
|
88
|
-
mergeByChain,
|
|
44
|
+
make,
|
|
89
45
|
merge,
|
|
90
46
|
forkBlockNumber,
|
|
91
47
|
}
|
|
92
|
-
/*
|
|
48
|
+
/* Utils Not a pure module */
|
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,6 +142,14 @@ 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, 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"
|
|
152
|
+
|
|
145
153
|
// Block numbers in `[fromBlock, belowBlock)` with a stored hash, ascending.
|
|
146
154
|
@send
|
|
147
155
|
external getHashedBlockNumbers: (t, ~fromBlock: int, ~belowBlock: int) => array<int> =
|
|
@@ -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: []}))
|
|
@@ -141,7 +143,9 @@ let make = (
|
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
|
|
144
|
-
let requestStats = [
|
|
146
|
+
let requestStats = [
|
|
147
|
+
{Source.method: "getLogs", seconds: pageFetchTime, responseBlocks: pageUnsafe.responseBlocks},
|
|
148
|
+
]
|
|
145
149
|
|
|
146
150
|
//set height and next from block
|
|
147
151
|
let knownHeight = pageUnsafe.archiveHeight
|