envio 3.15.0 → 3.16.0-subgraph
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -34
- package/evm.schema.json +11 -2
- package/fuel.schema.json +10 -1
- package/index.d.ts +6 -0
- package/licenses/README.md +1 -1
- package/package.json +10 -9
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +7 -0
- package/src/Bin.res.mjs +8 -0
- package/src/ChainFetching.res +450 -16
- package/src/ChainFetching.res.mjs +403 -32
- package/src/ChainState.res +124 -7
- package/src/ChainState.res.mjs +128 -67
- package/src/ChainState.resi +26 -0
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +31 -3
- package/src/Config.res.mjs +15 -4
- package/src/ContractRegisterContext.res +3 -6
- package/src/ContractRegisterContext.res.mjs +4 -2
- package/src/Core.res +95 -36
- package/src/Core.res.mjs +90 -1
- package/src/CrossChainState.res +12 -2
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +7 -4
- package/src/Ecosystem.res.mjs +8 -8
- package/src/EffectCacheLookup.res +98 -0
- package/src/EffectCacheLookup.res.mjs +116 -0
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/Env.res +20 -0
- package/src/Env.res.mjs +16 -0
- package/src/EventProcessing.res +38 -1
- package/src/EventProcessing.res.mjs +28 -1
- package/src/FetchState.res +408 -73
- package/src/FetchState.res.mjs +361 -91
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +39 -15
- package/src/HandlerLoader.res.mjs +27 -8
- package/src/HandlerRegister.res +4 -0
- package/src/HandlerRegister.res.mjs +5 -2
- package/src/HandlerRegister.resi +2 -0
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +61 -49
- package/src/Internal.res.mjs +36 -80
- package/src/LoadLayer.res +54 -15
- package/src/LoadLayer.res.mjs +75 -45
- package/src/LoadLayer.resi +26 -0
- package/src/Main.res +14 -1
- package/src/Main.res.mjs +4 -3
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/PreloadLookahead.res +202 -0
- package/src/PreloadLookahead.res.mjs +218 -0
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/RunScope.res +3 -0
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +42 -26
- package/src/SimulateItems.res.mjs +40 -16
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +303 -948
- package/src/Storage.res.mjs +229 -708
- package/src/SubgraphLog.res +19 -0
- package/src/SubgraphLog.res.mjs +26 -0
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/SyncWrites.res +107 -0
- package/src/SyncWrites.res.mjs +98 -0
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/UserContext.res +419 -46
- package/src/UserContext.res.mjs +318 -30
- package/src/Utils.res +17 -6
- package/src/Utils.res.mjs +12 -6
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +108 -174
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/AddressSet.res +2 -0
- package/src/sources/AddressStore.res +3 -0
- package/src/sources/CallSource.res +274 -0
- package/src/sources/CallSource.res.mjs +196 -0
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +10 -1
- package/src/sources/EvmChain.res.mjs +6 -3
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSync.res +2 -1
- package/src/sources/HyperSync.res.mjs +2 -1
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +84 -77
- package/src/sources/SourceManager.res.mjs +17 -20
- package/src/sources/SourceManager.resi +3 -4
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/src/subgraph/abi-types.ts +84 -0
- package/src/subgraph/aggregations.ts +745 -0
- package/src/subgraph/as-package.ts +143 -0
- package/src/subgraph/assemblyscript-regex.ts +67 -0
- package/src/subgraph/assemblyscript.ts +731 -0
- package/src/subgraph/blocks.ts +398 -0
- package/src/subgraph/calls-source.ts +702 -0
- package/src/subgraph/calls.ts +258 -0
- package/src/subgraph/conformance.ts +106 -0
- package/src/subgraph/errors.ts +85 -0
- package/src/subgraph/graft.ts +73 -0
- package/src/subgraph/graph-cli-worker.mjs +35 -0
- package/src/subgraph/graph-cli.ts +900 -0
- package/src/subgraph/graph-node-decimal.ts +199 -0
- package/src/subgraph/graph-ts-enums.ts +28 -0
- package/src/subgraph/graph-ts-types/VERSION +2 -0
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
- package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
- package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
- package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
- package/src/subgraph/graph-ts-types/index.d.ts +102 -0
- package/src/subgraph/graph-ts.ts +4339 -0
- package/src/subgraph/hosts.ts +554 -0
- package/src/subgraph/log.ts +28 -0
- package/src/subgraph/receipts.ts +184 -0
- package/src/subgraph/register-slots.ts +93 -0
- package/src/subgraph/rollup.ts +109 -0
- package/src/subgraph/rpc.ts +337 -0
- package/src/subgraph/runtime.ts +2059 -0
- package/src/subgraph/scope.ts +176 -0
- package/src/subgraph/stats.ts +42 -0
- package/src/subgraph/template-instances.ts +66 -0
- package/src/subgraph/toolchain.ts +327 -0
- package/src/subgraph/transient.ts +176 -0
- package/svm.schema.json +11 -2
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -67
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Every line the subgraph runtime logs, and every line a mapping logs through
|
|
2
|
+
// graph-ts (`uinfo`, `uwarn`, ...), as it is logged. A test indexer's own logger
|
|
3
|
+
// is silent, so this is how a test reads them. Compiled to JavaScript so a test
|
|
4
|
+
// can import it from an installed envio, where TypeScript isn't stripped.
|
|
5
|
+
|
|
6
|
+
type listener = (string, string) => unit
|
|
7
|
+
|
|
8
|
+
let listeners: array<listener> = []
|
|
9
|
+
|
|
10
|
+
let onLog = (listener: listener) => {
|
|
11
|
+
listeners->Array.push(listener)
|
|
12
|
+
() =>
|
|
13
|
+
switch listeners->Array.indexOf(listener) {
|
|
14
|
+
| -1 => ()
|
|
15
|
+
| index => listeners->Array.splice(~start=index, ~remove=1, ~insert=[])
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let notify = (level, message) => listeners->Array.forEach(listener => listener(level, message))
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let listeners = [];
|
|
5
|
+
|
|
6
|
+
function onLog(listener) {
|
|
7
|
+
listeners.push(listener);
|
|
8
|
+
return () => {
|
|
9
|
+
let index = listeners.indexOf(listener);
|
|
10
|
+
if (index !== -1) {
|
|
11
|
+
listeners.splice(index, 1);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function notify(level, message) {
|
|
18
|
+
listeners.forEach(listener => listener(level, message));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
listeners,
|
|
23
|
+
onLog,
|
|
24
|
+
notify,
|
|
25
|
+
}
|
|
26
|
+
/* No side effect */
|
package/src/Supervisor.res
CHANGED
|
@@ -374,74 +374,93 @@ let releaseIfAtHead = group =>
|
|
|
374
374
|
)
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
// The run's chains as
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
|
|
377
|
+
// The run's chains as a worker reports them before it has fetched anything:
|
|
378
|
+
// where `ChainState.makeFromDbState` resumes them. A display draws these for a
|
|
379
|
+
// worker it hasn't heard from yet, and its first sight of a chain is what it
|
|
380
|
+
// measures the sync pace from, so a resumed chain drawn from its start block
|
|
381
|
+
// would pass the earlier runs' progress off as this one's.
|
|
382
|
+
let resumedChains = (config: Config.t, ~resumed: array<Persistence.initialChainState>): array<
|
|
383
|
+
Metrics.chainMetrics,
|
|
384
|
+
> =>
|
|
381
385
|
config.chainMap
|
|
382
386
|
->ChainMap.values
|
|
383
387
|
->Array.map((chain): Metrics.chainMetrics => {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
timestampCaughtUpToHeadOrEndblock
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
388
|
+
let row = resumed->Array.find(row => row.id == chain.id)
|
|
389
|
+
let startBlock = row->Option.mapOr(chain->Config.startBlockOrZero, row => row.startBlock)
|
|
390
|
+
let endBlock = row->Option.mapOr(chain.endBlock, row => row.endBlock)
|
|
391
|
+
let progressBlockNumber = switch row {
|
|
392
|
+
| Some({progressBlockNumber}) if progressBlockNumber >= 0 => progressBlockNumber
|
|
393
|
+
| _ => startBlock - 1
|
|
394
|
+
}
|
|
395
|
+
let sourceBlockNumber = row->Option.mapOr(0, row => row.sourceBlockNumber)
|
|
396
|
+
let timestampCaughtUpToHeadOrEndblock =
|
|
397
|
+
row->Option.flatMap(row => row.timestampCaughtUpToHeadOrEndblock)
|
|
398
|
+
let metrics: Metrics.chainMetrics = {
|
|
399
|
+
chainId: chain.id,
|
|
400
|
+
poweredByHyperSync: switch chain.sourceConfig {
|
|
401
|
+
| EvmSourceConfig({hypersync}) => hypersync->Option.isSome
|
|
402
|
+
| FuelSourceConfig(_) | SvmSourceConfig(_) => true
|
|
403
|
+
| SimulateSourceConfig(_) | CustomSources(_) => false
|
|
404
|
+
},
|
|
405
|
+
firstEventBlockNumber: row->Option.flatMap(row => row.firstEventBlockNumber),
|
|
406
|
+
latestProcessedBlock: progressBlockNumber === -1 ? None : Some(progressBlockNumber),
|
|
407
|
+
timestampCaughtUpToHeadOrEndblock,
|
|
408
|
+
numEventsProcessed: row->Option.mapOr(0., row => row.numEventsProcessed),
|
|
409
|
+
latestFetchedBlockNumber: Pervasives.max(progressBlockNumber, 0),
|
|
410
|
+
knownHeight: sourceBlockNumber,
|
|
411
|
+
numBatchesFetched: 0,
|
|
412
|
+
startBlock,
|
|
413
|
+
endBlock,
|
|
414
|
+
numAddresses: 0,
|
|
415
|
+
addressesByContract: [],
|
|
416
|
+
isReady: timestampCaughtUpToHeadOrEndblock->Option.isSome,
|
|
417
|
+
sourceBlockNumber,
|
|
418
|
+
progressBlockNumber,
|
|
419
|
+
progressLatencyMs: None,
|
|
420
|
+
progressBlockTime: row->Option.flatMap(row => row.progressBlockTime),
|
|
421
|
+
concurrency: 0,
|
|
422
|
+
partitionsCount: 0,
|
|
423
|
+
bufferSize: 0,
|
|
424
|
+
bufferBlockNumber: progressBlockNumber,
|
|
425
|
+
idleSeconds: 0.,
|
|
426
|
+
waitingForNewBlockSeconds: 0.,
|
|
427
|
+
queryingSeconds: 0.,
|
|
428
|
+
blockRangeFetchSeconds: 0.,
|
|
429
|
+
blockRangeParseSeconds: 0.,
|
|
430
|
+
blockRangeFetchCount: 0.,
|
|
431
|
+
blockRangeFetchedEvents: 0.,
|
|
432
|
+
blockRangeFetchedBlocks: 0.,
|
|
433
|
+
reorgCount: 0,
|
|
434
|
+
reorgDetectedBlock: None,
|
|
435
|
+
rollbackTargetBlock: None,
|
|
436
|
+
rateLimitTimeMs: 0.,
|
|
437
|
+
rateLimitResetInMs: None,
|
|
438
|
+
}
|
|
439
|
+
switch (metrics->Metrics.hasProcessedToEndblock, endBlock) {
|
|
440
|
+
| (true, Some(endBlock)) => {...metrics, knownHeight: endBlock}
|
|
441
|
+
| _ => metrics
|
|
442
|
+
}
|
|
428
443
|
})
|
|
429
444
|
|
|
430
445
|
// Per worker rather than all or nothing: a worker done within its first report
|
|
431
446
|
// interval is heard from only as it exits, and a display holding just its
|
|
432
447
|
// siblings' finished chains would read as synced while it still indexes.
|
|
433
|
-
let displayedSnapshots = (
|
|
434
|
-
|
|
448
|
+
let displayedSnapshots = (
|
|
449
|
+
running: array<running>,
|
|
450
|
+
~resumedChains: array<Metrics.chainMetrics>,
|
|
451
|
+
~empty: Metrics.t,
|
|
452
|
+
) =>
|
|
435
453
|
running->Array.map(r =>
|
|
436
454
|
switch r.snapshot {
|
|
437
455
|
| Some(snapshot) => snapshot
|
|
438
456
|
| None => {
|
|
439
457
|
...empty,
|
|
440
|
-
chains:
|
|
458
|
+
chains: resumedChains->Array.filter(chain =>
|
|
459
|
+
r.worker.chainIds->Array.includes(chain.chainId)
|
|
460
|
+
),
|
|
441
461
|
}
|
|
442
462
|
}
|
|
443
463
|
)
|
|
444
|
-
}
|
|
445
464
|
|
|
446
465
|
// Runs the group: creates the schema for every chain, forks a worker per plan
|
|
447
466
|
// entry, and serves the run's metrics, console and display from what they
|
|
@@ -481,10 +500,9 @@ let run = async (~config: Config.t, ~logger, ~workers: array<worker>, ~reset) =>
|
|
|
481
500
|
let shouldUseTui = Tui.shouldUse()
|
|
482
501
|
// A run that resumed with every chain already caught up owes nobody a wait:
|
|
483
502
|
// its workers start realtime and there is no barrier to open.
|
|
503
|
+
let resumed = (persistence->Persistence.getInitializedState).chains
|
|
484
504
|
let holdRealtime =
|
|
485
|
-
|
|
486
|
-
chain.timestampCaughtUpToHeadOrEndblock->Option.isNone
|
|
487
|
-
)
|
|
505
|
+
resumed->Array.some(chain => chain.timestampCaughtUpToHeadOrEndblock->Option.isNone)
|
|
488
506
|
let group = {running: [], stopping: false, holdingRealtime: holdRealtime}
|
|
489
507
|
group.running =
|
|
490
508
|
workers->Array.mapWithIndex((worker, workerIndex) =>
|
|
@@ -534,8 +552,9 @@ let run = async (~config: Config.t, ~logger, ~workers: array<worker>, ~reset) =>
|
|
|
534
552
|
)
|
|
535
553
|
|
|
536
554
|
if shouldUseTui {
|
|
555
|
+
let resumedChains = resumedChains(config, ~resumed)
|
|
537
556
|
Tui.start(~config, ~logger, ~getMetrics=() =>
|
|
538
|
-
group.running->displayedSnapshots(~
|
|
557
|
+
group.running->displayedSnapshots(~resumedChains, ~empty=[]->merge)->merge
|
|
539
558
|
)
|
|
540
559
|
}
|
|
541
560
|
|
package/src/Supervisor.res.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
22
22
|
import * as Child_process from "child_process";
|
|
23
23
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
24
24
|
import * as CrossChainState from "./CrossChainState.res.mjs";
|
|
25
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
25
26
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
26
27
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
27
28
|
|
|
@@ -313,8 +314,20 @@ function releaseIfAtHead(group) {
|
|
|
313
314
|
}
|
|
314
315
|
}
|
|
315
316
|
|
|
316
|
-
function
|
|
317
|
+
function resumedChains(config, resumed) {
|
|
317
318
|
return ChainMap.values(config.chainMap).map(chain => {
|
|
319
|
+
let row = resumed.find(row => Primitive_object.equal(row.id, chain.id));
|
|
320
|
+
let startBlock = Stdlib_Option.mapOr(row, Config.startBlockOrZero(chain), row => row.startBlock);
|
|
321
|
+
let endBlock = Stdlib_Option.mapOr(row, chain.endBlock, row => row.endBlock);
|
|
322
|
+
let progressBlockNumber;
|
|
323
|
+
if (row !== undefined) {
|
|
324
|
+
let progressBlockNumber$1 = row.progressBlockNumber;
|
|
325
|
+
progressBlockNumber = progressBlockNumber$1 >= 0 ? progressBlockNumber$1 : startBlock - 1 | 0;
|
|
326
|
+
} else {
|
|
327
|
+
progressBlockNumber = startBlock - 1 | 0;
|
|
328
|
+
}
|
|
329
|
+
let sourceBlockNumber = Stdlib_Option.mapOr(row, 0, row => row.sourceBlockNumber);
|
|
330
|
+
let timestampCaughtUpToHeadOrEndblock = Stdlib_Option.flatMap(row, row => row.timestampCaughtUpToHeadOrEndblock);
|
|
318
331
|
let match = chain.sourceConfig;
|
|
319
332
|
let tmp;
|
|
320
333
|
switch (match.TAG) {
|
|
@@ -330,32 +343,37 @@ function configuredChains(config) {
|
|
|
330
343
|
tmp = false;
|
|
331
344
|
break;
|
|
332
345
|
}
|
|
333
|
-
let
|
|
334
|
-
let
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
346
|
+
let metrics_chainId = chain.id;
|
|
347
|
+
let metrics_firstEventBlockNumber = Stdlib_Option.flatMap(row, row => row.firstEventBlockNumber);
|
|
348
|
+
let metrics_latestProcessedBlock = progressBlockNumber === -1 ? undefined : progressBlockNumber;
|
|
349
|
+
let metrics_numEventsProcessed = Stdlib_Option.mapOr(row, 0, row => row.numEventsProcessed);
|
|
350
|
+
let metrics_latestFetchedBlockNumber = Primitive_int.max(progressBlockNumber, 0);
|
|
351
|
+
let metrics_addressesByContract = [];
|
|
352
|
+
let metrics_isReady = Stdlib_Option.isSome(timestampCaughtUpToHeadOrEndblock);
|
|
353
|
+
let metrics_progressBlockTime = Stdlib_Option.flatMap(row, row => row.progressBlockTime);
|
|
354
|
+
let metrics = {
|
|
355
|
+
chainId: metrics_chainId,
|
|
338
356
|
poweredByHyperSync: tmp,
|
|
339
|
-
firstEventBlockNumber:
|
|
340
|
-
latestProcessedBlock:
|
|
341
|
-
timestampCaughtUpToHeadOrEndblock:
|
|
342
|
-
numEventsProcessed:
|
|
343
|
-
latestFetchedBlockNumber:
|
|
344
|
-
knownHeight:
|
|
357
|
+
firstEventBlockNumber: metrics_firstEventBlockNumber,
|
|
358
|
+
latestProcessedBlock: metrics_latestProcessedBlock,
|
|
359
|
+
timestampCaughtUpToHeadOrEndblock: timestampCaughtUpToHeadOrEndblock,
|
|
360
|
+
numEventsProcessed: metrics_numEventsProcessed,
|
|
361
|
+
latestFetchedBlockNumber: metrics_latestFetchedBlockNumber,
|
|
362
|
+
knownHeight: sourceBlockNumber,
|
|
345
363
|
numBatchesFetched: 0,
|
|
346
|
-
startBlock:
|
|
347
|
-
endBlock:
|
|
364
|
+
startBlock: startBlock,
|
|
365
|
+
endBlock: endBlock,
|
|
348
366
|
numAddresses: 0,
|
|
349
|
-
addressesByContract:
|
|
350
|
-
isReady:
|
|
351
|
-
sourceBlockNumber:
|
|
352
|
-
progressBlockNumber:
|
|
367
|
+
addressesByContract: metrics_addressesByContract,
|
|
368
|
+
isReady: metrics_isReady,
|
|
369
|
+
sourceBlockNumber: sourceBlockNumber,
|
|
370
|
+
progressBlockNumber: progressBlockNumber,
|
|
353
371
|
progressLatencyMs: undefined,
|
|
354
|
-
progressBlockTime:
|
|
372
|
+
progressBlockTime: metrics_progressBlockTime,
|
|
355
373
|
concurrency: 0,
|
|
356
374
|
partitionsCount: 0,
|
|
357
375
|
bufferSize: 0,
|
|
358
|
-
bufferBlockNumber:
|
|
376
|
+
bufferBlockNumber: progressBlockNumber,
|
|
359
377
|
idleSeconds: 0,
|
|
360
378
|
waitingForNewBlockSeconds: 0,
|
|
361
379
|
queryingSeconds: 0,
|
|
@@ -370,18 +388,27 @@ function configuredChains(config) {
|
|
|
370
388
|
rateLimitTimeMs: 0,
|
|
371
389
|
rateLimitResetInMs: undefined
|
|
372
390
|
};
|
|
391
|
+
let match$1 = Metrics.hasProcessedToEndblock(metrics);
|
|
392
|
+
if (!match$1) {
|
|
393
|
+
return metrics;
|
|
394
|
+
}
|
|
395
|
+
if (endBlock === undefined) {
|
|
396
|
+
return metrics;
|
|
397
|
+
}
|
|
398
|
+
let newrecord = {...metrics};
|
|
399
|
+
newrecord.knownHeight = endBlock;
|
|
400
|
+
return newrecord;
|
|
373
401
|
});
|
|
374
402
|
}
|
|
375
403
|
|
|
376
|
-
function displayedSnapshots(running,
|
|
377
|
-
let configured = configuredChains(config);
|
|
404
|
+
function displayedSnapshots(running, resumedChains, empty) {
|
|
378
405
|
return running.map(r => {
|
|
379
406
|
let snapshot = r.snapshot;
|
|
380
407
|
if (snapshot !== undefined) {
|
|
381
408
|
return snapshot;
|
|
382
409
|
}
|
|
383
410
|
let newrecord = {...empty};
|
|
384
|
-
newrecord.chains =
|
|
411
|
+
newrecord.chains = resumedChains.filter(chain => r.worker.chainIds.includes(chain.chainId));
|
|
385
412
|
return newrecord;
|
|
386
413
|
});
|
|
387
414
|
}
|
|
@@ -402,7 +429,8 @@ async function run(config, logger, workers, reset) {
|
|
|
402
429
|
maxConnections: Env.Db.maxConnections
|
|
403
430
|
});
|
|
404
431
|
let shouldUseTui = Tui.shouldUse(undefined, undefined);
|
|
405
|
-
let
|
|
432
|
+
let resumed = Persistence.getInitializedState(persistence).chains;
|
|
433
|
+
let holdRealtime = resumed.some(chain => Stdlib_Option.isNone(chain.timestampCaughtUpToHeadOrEndblock));
|
|
406
434
|
let group = {
|
|
407
435
|
running: [],
|
|
408
436
|
stopping: false,
|
|
@@ -421,7 +449,8 @@ async function run(config, logger, workers, reset) {
|
|
|
421
449
|
runtime
|
|
422
450
|
]))), config.isDev);
|
|
423
451
|
if (shouldUseTui) {
|
|
424
|
-
|
|
452
|
+
let resumedChains$1 = resumedChains(config, resumed);
|
|
453
|
+
Tui.start(config, logger, () => merge(displayedSnapshots(group.running, resumedChains$1, merge([]))));
|
|
425
454
|
}
|
|
426
455
|
process.on("SIGTERM", () => stop(group));
|
|
427
456
|
process.on("SIGINT", () => stop(group));
|
|
@@ -465,7 +494,7 @@ export {
|
|
|
465
494
|
awaitExit,
|
|
466
495
|
isRunAtHead,
|
|
467
496
|
releaseIfAtHead,
|
|
468
|
-
|
|
497
|
+
resumedChains,
|
|
469
498
|
displayedSnapshots,
|
|
470
499
|
run,
|
|
471
500
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// The writes one round of a synchronous handler has made. A round that
|
|
2
|
+
// suspends is replayed from the top, so its writes are held here rather than
|
|
3
|
+
// applied: the replay has to see the store exactly as the first round did, or a
|
|
4
|
+
// read-modify-write lands once per round.
|
|
5
|
+
|
|
6
|
+
// A Map rather than a dict: every round makes a fresh one keyed by ids no
|
|
7
|
+
// other round shares, and a dict would give each of them its own hidden class.
|
|
8
|
+
type table = {
|
|
9
|
+
entityConfig: Internal.entityConfig,
|
|
10
|
+
scope: Internal.chainScope,
|
|
11
|
+
changes: Map.t<string, Change.t<Internal.entity>>,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// A handler runs on one chain, so an entity's scope is fixed for the whole
|
|
15
|
+
// round and the entity name is enough to key its table.
|
|
16
|
+
type t = dict<table>
|
|
17
|
+
|
|
18
|
+
let make = (): t => Dict.make()
|
|
19
|
+
|
|
20
|
+
let record = (writes: t, ~entityConfig: Internal.entityConfig, ~scope, change) => {
|
|
21
|
+
let table = switch writes->Utils.Dict.dangerouslyGetNonOption(entityConfig.name) {
|
|
22
|
+
| Some(table) => table
|
|
23
|
+
| None =>
|
|
24
|
+
let table = {entityConfig, scope, changes: Map.make()}
|
|
25
|
+
writes->Dict.set(entityConfig.name, table)
|
|
26
|
+
table
|
|
27
|
+
}
|
|
28
|
+
table.changes->Map.set(entityConfig.table.entityIdToKey(change->Change.getEntityId), change)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let changesOf = (writes: t, ~entityConfig: Internal.entityConfig) =>
|
|
32
|
+
switch writes->Utils.Dict.dangerouslyGetNonOption(entityConfig.name) {
|
|
33
|
+
| Some({changes}) => Some(changes)
|
|
34
|
+
| None => None
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// `Some(None)` is a delete this round made: the entity is known not to exist.
|
|
38
|
+
let getById = (writes: t, ~entityConfig: Internal.entityConfig, ~entityId: string) =>
|
|
39
|
+
switch writes->changesOf(~entityConfig) {
|
|
40
|
+
| Some(changes) =>
|
|
41
|
+
changes
|
|
42
|
+
->Map.get(entityConfig.table.entityIdToKey(entityId->EntityId.unsafeOfString))
|
|
43
|
+
->Option.map(InMemoryTable.Entity.mapChangeToEntity)
|
|
44
|
+
| None => None
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// What the store answered, as it reads once this round's writes land: a row
|
|
48
|
+
// the round rewrote is re-tested against the filter, and one it created joins.
|
|
49
|
+
let overlayFilter = (
|
|
50
|
+
writes: t,
|
|
51
|
+
entities: array<Internal.entity>,
|
|
52
|
+
~entityConfig: Internal.entityConfig,
|
|
53
|
+
~filter: EntityFilter.t,
|
|
54
|
+
) =>
|
|
55
|
+
switch writes->changesOf(~entityConfig) {
|
|
56
|
+
| None => entities
|
|
57
|
+
| Some(changes) =>
|
|
58
|
+
let matches = filter->EntityFilter.makeMatcher(~table=entityConfig.table)
|
|
59
|
+
let untouched =
|
|
60
|
+
entities->Array.filter(entity =>
|
|
61
|
+
!(
|
|
62
|
+
changes->Map.has(
|
|
63
|
+
entityConfig.table.entityIdToKey(
|
|
64
|
+
(entity->(Utils.magic: Internal.entity => {"id": EntityId.t}))["id"],
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
let written = []
|
|
70
|
+
changes->Map.forEach(change =>
|
|
71
|
+
switch change->InMemoryTable.Entity.mapChangeToEntity {
|
|
72
|
+
| Some(entity) if matches(entity) => written->Array.push(entity)->ignore
|
|
73
|
+
| _ => ()
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
untouched->Array.concat(written)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// How a change lands in the in-memory store, whether written directly or
|
|
80
|
+
// committed at the end of a round.
|
|
81
|
+
let write = (indexerState, ~entityConfig: Internal.entityConfig, ~scope, change) => {
|
|
82
|
+
switch change {
|
|
83
|
+
| Change.Set({entityId}) =>
|
|
84
|
+
PreloadLookahead.onSet(
|
|
85
|
+
~entityName=entityConfig.name,
|
|
86
|
+
~scope,
|
|
87
|
+
~entityId=entityConfig.table.entityIdToKey(entityId),
|
|
88
|
+
)
|
|
89
|
+
| Delete(_) => ()
|
|
90
|
+
}
|
|
91
|
+
indexerState
|
|
92
|
+
->InMemoryStore.getInMemTable(~entityConfig, ~scope)
|
|
93
|
+
->InMemoryTable.Entity.set(
|
|
94
|
+
~committedCheckpointId=indexerState->IndexerState.committedCheckpointIdFor(~scope),
|
|
95
|
+
change,
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let forEachChange = (writes: t, fn) =>
|
|
100
|
+
writes->Utils.Dict.forEach(({entityConfig, scope, changes}) =>
|
|
101
|
+
changes->Map.forEach(change => fn(~entityConfig, ~scope, change))
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
let commit = (writes: t, ~indexerState) =>
|
|
105
|
+
writes->Utils.Dict.forEach(({entityConfig, scope, changes}) =>
|
|
106
|
+
changes->Map.forEach(change => indexerState->write(~entityConfig, ~scope, change))
|
|
107
|
+
)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Utils from "./Utils.res.mjs";
|
|
4
|
+
import * as EntityFilter from "./db/EntityFilter.res.mjs";
|
|
5
|
+
import * as IndexerState from "./IndexerState.res.mjs";
|
|
6
|
+
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
7
|
+
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
8
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
|
+
import * as PreloadLookahead from "./PreloadLookahead.res.mjs";
|
|
10
|
+
|
|
11
|
+
function make() {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function record(writes, entityConfig, scope, change) {
|
|
16
|
+
let table = writes[entityConfig.name];
|
|
17
|
+
let table$1;
|
|
18
|
+
if (table !== undefined) {
|
|
19
|
+
table$1 = table;
|
|
20
|
+
} else {
|
|
21
|
+
let table_changes = new Map();
|
|
22
|
+
let table$2 = {
|
|
23
|
+
entityConfig: entityConfig,
|
|
24
|
+
scope: scope,
|
|
25
|
+
changes: table_changes
|
|
26
|
+
};
|
|
27
|
+
writes[entityConfig.name] = table$2;
|
|
28
|
+
table$1 = table$2;
|
|
29
|
+
}
|
|
30
|
+
table$1.changes.set(entityConfig.table.entityIdToKey(change.entityId), change);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function changesOf(writes, entityConfig) {
|
|
34
|
+
let match = writes[entityConfig.name];
|
|
35
|
+
if (match !== undefined) {
|
|
36
|
+
return match.changes;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getById(writes, entityConfig, entityId) {
|
|
41
|
+
let changes = changesOf(writes, entityConfig);
|
|
42
|
+
if (changes !== undefined) {
|
|
43
|
+
return Stdlib_Option.map(changes.get(entityConfig.table.entityIdToKey(entityId)), InMemoryTable.Entity.mapChangeToEntity);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function overlayFilter(writes, entities, entityConfig, filter) {
|
|
48
|
+
let changes = changesOf(writes, entityConfig);
|
|
49
|
+
if (changes === undefined) {
|
|
50
|
+
return entities;
|
|
51
|
+
}
|
|
52
|
+
let matches = EntityFilter.makeMatcher(filter, entityConfig.table);
|
|
53
|
+
let untouched = entities.filter(entity => !changes.has(entityConfig.table.entityIdToKey(entity.id)));
|
|
54
|
+
let written = [];
|
|
55
|
+
changes.forEach(change => {
|
|
56
|
+
let entity = InMemoryTable.Entity.mapChangeToEntity(change);
|
|
57
|
+
if (entity !== undefined && matches(entity)) {
|
|
58
|
+
written.push(entity);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return untouched.concat(written);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function write(indexerState, entityConfig, scope, change) {
|
|
66
|
+
if (change.type === "SET") {
|
|
67
|
+
PreloadLookahead.onSet(entityConfig.name, scope, entityConfig.table.entityIdToKey(change.entityId));
|
|
68
|
+
}
|
|
69
|
+
InMemoryTable.Entity.set(InMemoryStore.getInMemTable(indexerState, entityConfig, scope), IndexerState.committedCheckpointIdFor(indexerState, scope), change);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function forEachChange(writes, fn) {
|
|
73
|
+
Utils.Dict.forEach(writes, param => {
|
|
74
|
+
let scope = param.scope;
|
|
75
|
+
let entityConfig = param.entityConfig;
|
|
76
|
+
param.changes.forEach(change => fn(entityConfig, scope, change));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function commit(writes, indexerState) {
|
|
81
|
+
Utils.Dict.forEach(writes, param => {
|
|
82
|
+
let scope = param.scope;
|
|
83
|
+
let entityConfig = param.entityConfig;
|
|
84
|
+
param.changes.forEach(change => write(indexerState, entityConfig, scope, change));
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
make,
|
|
90
|
+
record,
|
|
91
|
+
changesOf,
|
|
92
|
+
getById,
|
|
93
|
+
overlayFilter,
|
|
94
|
+
write,
|
|
95
|
+
forEachChange,
|
|
96
|
+
commit,
|
|
97
|
+
}
|
|
98
|
+
/* Utils Not a pure module */
|