envio 3.11.0 → 3.12.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/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/ChainState.res +72 -19
- package/src/ChainState.res.mjs +50 -12
- package/src/ChainState.resi +5 -0
- package/src/Config.res +58 -37
- package/src/Config.res.mjs +63 -53
- package/src/CrossChainState.res +49 -52
- 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 +14 -0
- package/src/FetchState.res.mjs +14 -0
- 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/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 +11 -4
- package/src/LoadLayer.res.mjs +8 -5
- 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 +194 -118
- package/src/PgStorage.res.mjs +132 -72
- 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 +5 -5
- package/src/TestIndexer.res.mjs +7 -6
- package/src/UserContext.res +7 -4
- package/src/UserContext.res.mjs +5 -2
- package/src/Utils.res +9 -0
- package/src/Utils.res.mjs +9 -0
- 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/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/sources/BlockStore.res +3 -0
- package/src/sources/EvmHyperSyncSource.res +3 -1
- package/src/sources/EvmHyperSyncSource.res.mjs +2 -1
- package/src/sources/HyperSync.res +2 -0
- package/src/sources/HyperSync.res.mjs +1 -0
- package/src/sources/HyperSync.resi +1 -0
- package/src/sources/HyperSyncClient.res +3 -0
- package/src/sources/RequestStat.res +8 -1
- package/src/sources/Source.res +4 -3
- package/src/sources/SourceManager.res +30 -10
- package/src/sources/SourceManager.res.mjs +24 -7
- package/src/sources/SourceManager.resi +2 -0
- 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
package/src/db/InternalTable.res
CHANGED
|
@@ -170,6 +170,7 @@ FROM "${pgSchema}"."${table.tableName}";`
|
|
|
170
170
|
module Chains = {
|
|
171
171
|
type progressFields = [
|
|
172
172
|
| #progress_block
|
|
173
|
+
| #progress_block_time
|
|
173
174
|
| #events_processed
|
|
174
175
|
| #source_block
|
|
175
176
|
]
|
|
@@ -186,6 +187,7 @@ module Chains = {
|
|
|
186
187
|
| #buffer_block
|
|
187
188
|
| #ready_at
|
|
188
189
|
| #_is_hyper_sync
|
|
190
|
+
| #checkpoint_id
|
|
189
191
|
]
|
|
190
192
|
|
|
191
193
|
let fields: array<field> = [
|
|
@@ -198,19 +200,16 @@ module Chains = {
|
|
|
198
200
|
#first_event_block,
|
|
199
201
|
#buffer_block,
|
|
200
202
|
#progress_block,
|
|
203
|
+
#progress_block_time,
|
|
201
204
|
#ready_at,
|
|
202
205
|
#events_processed,
|
|
203
206
|
#_is_hyper_sync,
|
|
207
|
+
#checkpoint_id,
|
|
204
208
|
]
|
|
205
209
|
|
|
206
210
|
type metaFields = {
|
|
207
211
|
@as("first_event_block")
|
|
208
|
-
firstEventBlockNumber: Null.t<
|
|
209
|
-
// Push id first (for WHERE clause)
|
|
210
|
-
|
|
211
|
-
// Then push all updateable field values (for SET clause)
|
|
212
|
-
int,
|
|
213
|
-
>,
|
|
212
|
+
firstEventBlockNumber: Null.t<int>,
|
|
214
213
|
@as("buffer_block") latestFetchedBlockNumber: int,
|
|
215
214
|
@as("ready_at")
|
|
216
215
|
timestampCaughtUpToHeadOrEndblock: Null.t<Date.t>,
|
|
@@ -225,7 +224,9 @@ module Chains = {
|
|
|
225
224
|
@as("max_reorg_depth") maxReorgDepth: int,
|
|
226
225
|
@as("source_block") blockHeight: int,
|
|
227
226
|
@as("progress_block") progressBlockNumber: int,
|
|
227
|
+
@as("progress_block_time") progressBlockTime: Null.t<Date.t>,
|
|
228
228
|
@as("events_processed") numEventsProcessed: float,
|
|
229
|
+
@as("checkpoint_id") checkpointId: Internal.checkpointId,
|
|
229
230
|
...metaFields,
|
|
230
231
|
}
|
|
231
232
|
|
|
@@ -265,6 +266,22 @@ module Chains = {
|
|
|
265
266
|
mkField((#_is_hyper_sync: field :> string), Boolean, ~fieldSchema=S.bool),
|
|
266
267
|
// Fully processed block number
|
|
267
268
|
mkField((#progress_block: field :> string), Int32, ~fieldSchema=S.int),
|
|
269
|
+
// When the block in progress_block was produced, so that `now() -
|
|
270
|
+
// progress_block_time` is how far behind chain time the indexer is. Null
|
|
271
|
+
// while the source hasn't reported that block's header.
|
|
272
|
+
mkField(
|
|
273
|
+
(#progress_block_time: field :> string),
|
|
274
|
+
Date,
|
|
275
|
+
~fieldSchema=S.null(Utils.Schema.dbDate),
|
|
276
|
+
~isNullable,
|
|
277
|
+
),
|
|
278
|
+
// The last checkpoint id the chain has committed. Kept here rather than
|
|
279
|
+
// read off the checkpoints table: checkpoint rows are only written while
|
|
280
|
+
// a rollback could reach them, but an append-only sink holds a row for
|
|
281
|
+
// every id ever handed out and resolves current state through them, so a
|
|
282
|
+
// resume has to continue the sequence even where no checkpoint row backs
|
|
283
|
+
// it.
|
|
284
|
+
mkField((#checkpoint_id: field :> string), UInt64, ~fieldSchema=S.bigint),
|
|
268
285
|
],
|
|
269
286
|
)
|
|
270
287
|
|
|
@@ -280,8 +297,10 @@ module Chains = {
|
|
|
280
297
|
latestFetchedBlockNumber: -1,
|
|
281
298
|
timestampCaughtUpToHeadOrEndblock: Null.null,
|
|
282
299
|
progressBlockNumber: -1,
|
|
300
|
+
progressBlockTime: Null.null,
|
|
283
301
|
isHyperSync: false,
|
|
284
302
|
numEventsProcessed: 0.,
|
|
303
|
+
checkpointId: Internal.initialCheckpointId,
|
|
285
304
|
}
|
|
286
305
|
}
|
|
287
306
|
|
|
@@ -358,8 +377,11 @@ WHERE "${(#id: field :> string)}" = $2
|
|
|
358
377
|
timestampCaughtUpToHeadOrEndblock: Null.t<Date.t>,
|
|
359
378
|
numEventsProcessed: float,
|
|
360
379
|
progressBlockNumber: int,
|
|
380
|
+
progressBlockTime: Null.t<Date.t>,
|
|
361
381
|
addressRows: AddressRows.seedRows,
|
|
362
382
|
sourceBlockNumber: int,
|
|
383
|
+
// BIGINT, which the driver hands back as a string.
|
|
384
|
+
checkpointId: string,
|
|
363
385
|
}
|
|
364
386
|
|
|
365
387
|
let makeGetInitialStateQuery = (~pgSchema) => {
|
|
@@ -371,7 +393,9 @@ WHERE "${(#id: field :> string)}" = $2
|
|
|
371
393
|
"${(#ready_at: field :> string)}" as "timestampCaughtUpToHeadOrEndblock",
|
|
372
394
|
"${(#events_processed: field :> string)}"::float8 as "numEventsProcessed",
|
|
373
395
|
"${(#progress_block: field :> string)}" as "progressBlockNumber",
|
|
374
|
-
"${(#
|
|
396
|
+
"${(#progress_block_time: field :> string)}" as "progressBlockTime",
|
|
397
|
+
"${(#source_block: field :> string)}" as "sourceBlockNumber",
|
|
398
|
+
"${(#checkpoint_id: field :> string)}"::TEXT as "checkpointId"
|
|
375
399
|
FROM "${pgSchema}"."${table.tableName}";`
|
|
376
400
|
}
|
|
377
401
|
|
|
@@ -403,7 +427,20 @@ FROM "${pgSchema}"."${table.tableName}";`
|
|
|
403
427
|
})
|
|
404
428
|
}
|
|
405
429
|
|
|
406
|
-
|
|
430
|
+
// Block timestamps are unix seconds everywhere inside the indexer - that's
|
|
431
|
+
// what a block header carries - and a timestamp in storage, where `now() -
|
|
432
|
+
// progress_block_time` is the query the column exists for.
|
|
433
|
+
let blockTimeToDb = (blockTime: option<int>) =>
|
|
434
|
+
blockTime->Option.map(seconds => Date.fromTime(seconds->Int.toFloat *. 1000.))->Null.fromOption
|
|
435
|
+
let blockTimeFromDb = (date: Null.t<Date.t>) =>
|
|
436
|
+
date->Null.toOption->Option.map(date => (date->Date.getTime /. 1000.)->Float.toInt)
|
|
437
|
+
|
|
438
|
+
let progressFields: array<progressFields> = [
|
|
439
|
+
#progress_block,
|
|
440
|
+
#progress_block_time,
|
|
441
|
+
#events_processed,
|
|
442
|
+
#source_block,
|
|
443
|
+
]
|
|
407
444
|
|
|
408
445
|
let makeProgressFieldsUpdateQuery = (~pgSchema) => {
|
|
409
446
|
let setClauses = Array.mapWithIndex(progressFields, (field, index) => {
|
|
@@ -444,6 +481,7 @@ WHERE "id" = $1;`
|
|
|
444
481
|
type progressedChain = {
|
|
445
482
|
chainId: ChainId.t,
|
|
446
483
|
progressBlockNumber: int,
|
|
484
|
+
progressBlockTime: option<int>,
|
|
447
485
|
sourceBlockNumber: int,
|
|
448
486
|
totalEventsProcessed: float,
|
|
449
487
|
}
|
|
@@ -463,6 +501,8 @@ WHERE "id" = $1;`
|
|
|
463
501
|
->Array.push(
|
|
464
502
|
switch field {
|
|
465
503
|
| #progress_block => data.progressBlockNumber->(Utils.magic: int => unknown)
|
|
504
|
+
| #progress_block_time =>
|
|
505
|
+
data.progressBlockTime->blockTimeToDb->(Utils.magic: Null.t<Date.t> => unknown)
|
|
466
506
|
| #events_processed => data.totalEventsProcessed->(Utils.magic: float => unknown)
|
|
467
507
|
| #source_block => data.sourceBlockNumber->(Utils.magic: int => unknown)
|
|
468
508
|
},
|
|
@@ -475,6 +515,31 @@ WHERE "id" = $1;`
|
|
|
475
515
|
|
|
476
516
|
Promise.all(promises)->Utils.Promise.ignoreValue
|
|
477
517
|
}
|
|
518
|
+
|
|
519
|
+
let makeSetCheckpointFrontierQuery = (~pgSchema, ~chainIdMode: ChainId.mode=Int32) => {
|
|
520
|
+
let chainIdArrayType = chainIdArrayType(~pgSchema, ~chainIdMode)
|
|
521
|
+
`UPDATE "${pgSchema}"."${table.tableName}"
|
|
522
|
+
SET "${(#checkpoint_id: field :> string)}" = envio_frontier.checkpoint_id
|
|
523
|
+
FROM unnest($1::${chainIdArrayType},$2::${(BigInt: Postgres.columnType :> string)}[]) AS envio_frontier(chain_id, checkpoint_id)
|
|
524
|
+
WHERE "${table.tableName}"."${(#id: field :> string)}" = envio_frontier.chain_id;`
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// The chains the write moved, in one statement and in the batch's own
|
|
528
|
+
// transaction — so a chain's stored id can never outlive the rows it covers,
|
|
529
|
+
// nor lag behind them.
|
|
530
|
+
let setCheckpointFrontier = (
|
|
531
|
+
sql,
|
|
532
|
+
~pgSchema,
|
|
533
|
+
~frontier: Frontier.t,
|
|
534
|
+
~chainIdMode: ChainId.mode=Int32,
|
|
535
|
+
) => {
|
|
536
|
+
sql
|
|
537
|
+
->Postgres.preparedUnsafe(
|
|
538
|
+
makeSetCheckpointFrontierQuery(~pgSchema, ~chainIdMode),
|
|
539
|
+
frontier->Frontier.unnestParams->(Utils.magic: Frontier.unnestParams => unknown),
|
|
540
|
+
)
|
|
541
|
+
->Utils.Promise.ignoreValue
|
|
542
|
+
}
|
|
478
543
|
}
|
|
479
544
|
|
|
480
545
|
module EnvioInfo = {
|
|
@@ -556,31 +621,58 @@ module Checkpoints = {
|
|
|
556
621
|
|
|
557
622
|
let initialCheckpointId = 0n
|
|
558
623
|
|
|
624
|
+
// The checkpoint a rollback's diff rows are stamped with. It never reaches
|
|
625
|
+
// Postgres — there the diff is written straight to the entity table — but an
|
|
626
|
+
// append-only sink resolves current state through the checkpoints, so without
|
|
627
|
+
// one of these the diff sits above the frontier while the rows it supersedes
|
|
628
|
+
// sit below it, and the orphaned values are what a reader sees.
|
|
629
|
+
type diffCheckpoint = {
|
|
630
|
+
chainId: ChainId.t,
|
|
631
|
+
checkpointId: Internal.checkpointId,
|
|
632
|
+
// Where the rollback left the chain. At or below its stored progress, so a
|
|
633
|
+
// resume counts the row as covered rather than as something to trim back to.
|
|
634
|
+
blockNumber: int,
|
|
635
|
+
}
|
|
636
|
+
|
|
559
637
|
// One definition per column, carrying what each storage needs: the field
|
|
560
638
|
// itself, the type ClickHouse gives it where that differs from Postgres, and
|
|
561
|
-
// where a batch keeps the column's values.
|
|
639
|
+
// where a batch — or a rollback diff — keeps the column's values.
|
|
562
640
|
type column = {
|
|
563
641
|
field: fieldOrDerived,
|
|
564
642
|
clickHouseFieldType: fieldType,
|
|
565
643
|
valuesOf: Batch.t => array<unknown>,
|
|
644
|
+
diffValuesOf: array<diffCheckpoint> => array<unknown>,
|
|
566
645
|
}
|
|
567
646
|
|
|
647
|
+
// The chain leads the key: ids are only unique within a chain, and every
|
|
648
|
+
// query that narrows to one chain reads a contiguous run of it.
|
|
568
649
|
let columns: array<column> = [
|
|
569
650
|
{
|
|
570
|
-
field: mkField(
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
651
|
+
field: mkField(
|
|
652
|
+
(#chain_id: field :> string),
|
|
653
|
+
ChainId,
|
|
654
|
+
~fieldSchema=ChainId.schema,
|
|
655
|
+
~isPrimaryKey,
|
|
656
|
+
),
|
|
576
657
|
clickHouseFieldType: ChainId,
|
|
577
658
|
valuesOf: batch =>
|
|
578
659
|
batch.checkpointChainIds->(Utils.magic: array<ChainId.t> => array<unknown>),
|
|
660
|
+
diffValuesOf: diffs =>
|
|
661
|
+
diffs->Array.map(diff => diff.chainId->(Utils.magic: ChainId.t => unknown)),
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
field: mkField((#id: field :> string), UInt64, ~fieldSchema=S.bigint, ~isPrimaryKey),
|
|
665
|
+
clickHouseFieldType: UInt64,
|
|
666
|
+
valuesOf: batch => batch.checkpointIds->(Utils.magic: array<bigint> => array<unknown>),
|
|
667
|
+
diffValuesOf: diffs =>
|
|
668
|
+
diffs->Array.map(diff => diff.checkpointId->(Utils.magic: bigint => unknown)),
|
|
579
669
|
},
|
|
580
670
|
{
|
|
581
671
|
field: mkField((#block_number: field :> string), Int32, ~fieldSchema=S.int),
|
|
582
672
|
clickHouseFieldType: Int32,
|
|
583
673
|
valuesOf: batch => batch.checkpointBlockNumbers->(Utils.magic: array<int> => array<unknown>),
|
|
674
|
+
diffValuesOf: diffs =>
|
|
675
|
+
diffs->Array.map(diff => diff.blockNumber->(Utils.magic: int => unknown)),
|
|
584
676
|
},
|
|
585
677
|
{
|
|
586
678
|
field: mkField(
|
|
@@ -592,6 +684,8 @@ module Checkpoints = {
|
|
|
592
684
|
clickHouseFieldType: String,
|
|
593
685
|
valuesOf: batch =>
|
|
594
686
|
batch.checkpointBlockHashes->(Utils.magic: array<Null.t<string>> => array<unknown>),
|
|
687
|
+
diffValuesOf: diffs =>
|
|
688
|
+
diffs->Array.map(_ => Null.Null->(Utils.magic: Null.t<string> => unknown)),
|
|
595
689
|
},
|
|
596
690
|
{
|
|
597
691
|
field: mkField((#events_processed: field :> string), Int32, ~fieldSchema=S.int),
|
|
@@ -600,10 +694,34 @@ module Checkpoints = {
|
|
|
600
694
|
clickHouseFieldType: UInt64,
|
|
601
695
|
valuesOf: batch =>
|
|
602
696
|
batch.checkpointEventsProcessed->(Utils.magic: array<int> => array<unknown>),
|
|
697
|
+
diffValuesOf: diffs => diffs->Array.map(_ => 0->(Utils.magic: int => unknown)),
|
|
603
698
|
},
|
|
604
699
|
]
|
|
605
700
|
|
|
606
|
-
let
|
|
701
|
+
let tableName = "envio_checkpoints"
|
|
702
|
+
|
|
703
|
+
let table = mkTable(tableName, ~fields=columns->Array.map(({field}) => field))
|
|
704
|
+
|
|
705
|
+
// Where each chain counts its own ids the chain has to be part of the key,
|
|
706
|
+
// and every bound a rollback or a prune applies names it. Under one shared
|
|
707
|
+
// sequence the id is unique by itself and those bounds are id ranges with no
|
|
708
|
+
// chain in them — which a key led by the chain can't serve.
|
|
709
|
+
let globalTable = mkTable(
|
|
710
|
+
tableName,
|
|
711
|
+
~fields=columns->Array.map(({field: column}) =>
|
|
712
|
+
switch column {
|
|
713
|
+
| Table.Field(f) if f.fieldName === (#chain_id: field :> string) =>
|
|
714
|
+
Table.Field({...f, isPrimaryKey: false})
|
|
715
|
+
| column => column
|
|
716
|
+
}
|
|
717
|
+
),
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
let tableFor = (sequence: CheckpointSequence.t) =>
|
|
721
|
+
switch sequence {
|
|
722
|
+
| SharedAcrossChains => globalTable
|
|
723
|
+
| PerChain => table
|
|
724
|
+
}
|
|
607
725
|
|
|
608
726
|
let makeGetReorgCheckpointsQuery = (~pgSchema): string => {
|
|
609
727
|
// The safe_block checkpoint itself is included, so it can be used for safe
|
|
@@ -640,10 +758,6 @@ WHERE cp."${(#block_hash: field :> string)}" IS NOT NULL
|
|
|
640
758
|
ORDER BY cp."${(#id: field :> string)}";`
|
|
641
759
|
}
|
|
642
760
|
|
|
643
|
-
let makeCommitedCheckpointIdQuery = (~pgSchema) => {
|
|
644
|
-
`SELECT COALESCE(MAX(${(#id: field :> string)}), ${initialCheckpointId->BigInt.toString}) AS id FROM "${pgSchema}"."${table.tableName}";`
|
|
645
|
-
}
|
|
646
|
-
|
|
647
761
|
let makeInsertCheckpointQuery = (~pgSchema, ~chainIdMode: ChainId.mode=Int32) => {
|
|
648
762
|
let chainIdArrayType = chainIdArrayType(~pgSchema, ~chainIdMode)
|
|
649
763
|
`INSERT INTO "${pgSchema}"."${table.tableName}" ("${(#id: field :> string)}", "${(#chain_id: field :> string)}", "${(#block_number: field :> string)}", "${(#block_hash: field :> string)}", "${(#events_processed: field :> string)}")
|
|
@@ -687,18 +801,21 @@ SELECT * FROM unnest($1::${(BigInt: Postgres.columnType :> string)}[],$2::${chai
|
|
|
687
801
|
|
|
688
802
|
let rollback = (sql, ~pgSchema, ~floors: RollbackFloors.t) => {
|
|
689
803
|
let tableRef = `"${pgSchema}"."${table.tableName}"`
|
|
690
|
-
let bounds = floors.
|
|
804
|
+
let bounds = floors.checkpointBounds->CheckpointSequence.sql(~chainIdColumn, ~tableRef)
|
|
691
805
|
sql
|
|
692
806
|
->Postgres.preparedUnsafe(
|
|
693
807
|
`DELETE FROM ${tableRef}${bounds.using} WHERE "${(#id: field :> string)}" > ${bounds.checkpointId}${bounds.usingMatch};`,
|
|
694
|
-
floors.
|
|
808
|
+
floors.checkpointBounds->CheckpointSequence.params,
|
|
695
809
|
)
|
|
696
810
|
->Utils.Promise.ignoreValue
|
|
697
811
|
}
|
|
698
812
|
|
|
699
|
-
let makePruneStaleCheckpointsQuery = (
|
|
813
|
+
let makePruneStaleCheckpointsQuery = (
|
|
814
|
+
~pgSchema,
|
|
815
|
+
~safeCheckpoints: CheckpointSequence.checkpointBoundsByChain,
|
|
816
|
+
) => {
|
|
700
817
|
let tableRef = `"${pgSchema}"."${table.tableName}"`
|
|
701
|
-
let bounds = safeCheckpoints->
|
|
818
|
+
let bounds = safeCheckpoints->CheckpointSequence.sql(~chainIdColumn, ~tableRef)
|
|
702
819
|
`DELETE FROM ${tableRef}${bounds.using} WHERE "${(#id: field :> string)}" < ${bounds.checkpointId}${bounds.usingMatch};`
|
|
703
820
|
}
|
|
704
821
|
|
|
@@ -706,7 +823,7 @@ SELECT * FROM unnest($1::${(BigInt: Postgres.columnType :> string)}[],$2::${chai
|
|
|
706
823
|
sql
|
|
707
824
|
->Postgres.preparedUnsafe(
|
|
708
825
|
makePruneStaleCheckpointsQuery(~pgSchema, ~safeCheckpoints),
|
|
709
|
-
safeCheckpoints->
|
|
826
|
+
safeCheckpoints->CheckpointSequence.params,
|
|
710
827
|
)
|
|
711
828
|
->Utils.Promise.ignoreValue
|
|
712
829
|
|
|
@@ -738,7 +855,7 @@ LIMIT 1;`
|
|
|
738
855
|
}
|
|
739
856
|
|
|
740
857
|
let makeGetRollbackProgressDiffQuery = (~pgSchema, ~floors: RollbackFloors.t) => {
|
|
741
|
-
let bounds = floors.
|
|
858
|
+
let bounds = floors.checkpointBounds->CheckpointSequence.sql(~chainIdColumn, ~tableRef="t")
|
|
742
859
|
`SELECT
|
|
743
860
|
t."${(#chain_id: field :> string)}"::float8 as "${(#chain_id: field :> string)}",
|
|
744
861
|
SUM(t."${(#events_processed: field :> string)}") as events_processed_diff,
|
|
@@ -752,7 +869,7 @@ GROUP BY t."${(#chain_id: field :> string)}";`
|
|
|
752
869
|
sql
|
|
753
870
|
->Postgres.preparedUnsafe(
|
|
754
871
|
makeGetRollbackProgressDiffQuery(~pgSchema, ~floors),
|
|
755
|
-
floors.
|
|
872
|
+
floors.checkpointBounds->CheckpointSequence.params,
|
|
756
873
|
)
|
|
757
874
|
->(
|
|
758
875
|
Utils.magic: promise<unknown> => promise<
|
|
@@ -816,6 +933,7 @@ SELECT
|
|
|
816
933
|
"${(#start_block: Chains.field :> string)}" AS "startBlock",
|
|
817
934
|
"${(#end_block: Chains.field :> string)}" AS "endBlock",
|
|
818
935
|
"${(#progress_block: Chains.field :> string)}" AS "progressBlock",
|
|
936
|
+
"${(#progress_block_time: Chains.field :> string)}" AS "progressBlockTime",
|
|
819
937
|
"${(#buffer_block: Chains.field :> string)}" AS "bufferBlock",
|
|
820
938
|
"${(#first_event_block: Chains.field :> string)}" AS "firstEventBlock",
|
|
821
939
|
"${(#events_processed: Chains.field :> string)}"::float4 AS "eventsProcessed",
|
|
@@ -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",
|