envio 3.12.1 → 3.13.0-rc.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/package.json +6 -8
- package/src/BatchProcessing.res +15 -14
- package/src/BatchProcessing.res.mjs +8 -15
- package/src/Bin.res +24 -17
- package/src/Bin.res.mjs +5 -0
- package/src/ChainFetching.res +18 -24
- package/src/ChainFetching.res.mjs +14 -15
- package/src/ChainState.res +103 -38
- package/src/ChainState.res.mjs +79 -22
- package/src/ChainState.resi +14 -2
- package/src/Config.res +32 -0
- package/src/Config.res.mjs +24 -0
- package/src/Core.res +4 -0
- package/src/Core.res.mjs +4 -0
- package/src/CrossChainState.res +109 -11
- package/src/CrossChainState.res.mjs +71 -7
- package/src/CrossChainState.resi +11 -1
- package/src/Env.res +4 -0
- package/src/ErrorHandling.res +15 -4
- package/src/ErrorHandling.res.mjs +16 -5
- package/src/FinalizeBackfill.res +10 -4
- package/src/FinalizeBackfill.res.mjs +5 -3
- package/src/HandlerRegister.res +0 -37
- package/src/HandlerRegister.res.mjs +0 -18
- package/src/IndexerLoop.res +2 -0
- package/src/IndexerLoop.res.mjs +1 -0
- package/src/IndexerState.res +43 -1
- package/src/IndexerState.res.mjs +48 -4
- package/src/IndexerState.resi +11 -0
- package/src/Main.res +128 -268
- package/src/Main.res.mjs +27 -153
- package/src/Metrics.res +268 -102
- package/src/Metrics.res.mjs +227 -48
- package/src/Persistence.res +30 -2
- package/src/Persistence.res.mjs +12 -3
- package/src/PgStorage.res +19 -11
- package/src/PgStorage.res.mjs +13 -10
- package/src/Rollback.res +3 -3
- package/src/Server.res +178 -0
- package/src/Server.res.mjs +143 -0
- package/src/SimulateItems.res +1 -1
- package/src/SimulateItems.res.mjs +1 -1
- package/src/Supervisor.res +542 -0
- package/src/Supervisor.res.mjs +455 -0
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +2 -2
- package/src/Worker.res +101 -0
- package/src/Worker.res.mjs +81 -0
- package/src/bindings/NodeJs.res +50 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/db/InternalTable.res +8 -1
- package/src/db/InternalTable.res.mjs +5 -1
- package/src/sources/AddressSet.res +5 -3
- package/src/sources/AddressStore.res +19 -11
- package/src/sources/AddressStore.res.mjs +2 -7
- package/src/sources/BlockStore.res +10 -9
- package/src/sources/BlockStore.res.mjs +4 -4
- package/src/sources/ChainSources.res +4 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -0
- package/src/sources/EvmChain.res.mjs +3 -1
- package/src/sources/EvmEventItem.res +56 -0
- package/src/sources/EvmEventItem.res.mjs +32 -0
- package/src/sources/EvmHyperSyncSource.res +7 -37
- package/src/sources/EvmHyperSyncSource.res.mjs +8 -29
- package/src/sources/EvmRpcClient.res +41 -59
- package/src/sources/EvmRpcClient.res.mjs +4 -54
- package/src/sources/EvmRpcWs.res +4 -1
- package/src/sources/EvmRpcWs.res.mjs +6 -2
- package/src/sources/FuelHyperSyncSource.res +6 -4
- package/src/sources/FuelHyperSyncSource.res.mjs +7 -9
- package/src/sources/HeightFeed.res +7 -1
- package/src/sources/HeightFeed.res.mjs +9 -7
- package/src/sources/HyperSyncClient.res +1 -14
- package/src/sources/RequestStat.res +7 -0
- package/src/sources/RequestStat.res.mjs +14 -1
- package/src/sources/RpcSource.res +100 -1043
- package/src/sources/RpcSource.res.mjs +81 -1056
- package/src/sources/SimulateSource.res +2 -5
- package/src/sources/SimulateSource.res.mjs +2 -3
- package/src/sources/Source.res +34 -12
- package/src/sources/Source.res.mjs +11 -0
- package/src/sources/SourceManager.res +111 -31
- package/src/sources/SourceManager.res.mjs +65 -31
- package/src/sources/SourceManager.resi +4 -0
- package/src/sources/StartBlockResolver.res +8 -5
- package/src/sources/StartBlockResolver.res.mjs +4 -2
- package/src/sources/SvmHyperSyncSource.res +4 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +4 -6
- package/src/sources/TransactionStore.res +9 -6
- package/src/sources/TransactionStore.res.mjs +2 -2
- package/src/tui/Tui.res +10 -0
- package/src/tui/Tui.res.mjs +15 -0
- package/src/tui/components/SyncETA.res +12 -6
- package/src/tui/components/SyncETA.res.mjs +12 -8
- package/src/LazyLoader.res +0 -135
- package/src/LazyLoader.res.mjs +0 -118
- package/src/bindings/SDSL.res +0 -12
- package/src/bindings/SDSL.res.mjs +0 -9
- package/src/bindings/Yargs.res +0 -8
- package/src/bindings/Yargs.res.mjs +0 -2
- package/src/sources/Rpc.res +0 -185
- package/src/sources/Rpc.res.mjs +0 -183
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.0-rc.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -49,11 +49,9 @@
|
|
|
49
49
|
"@fuel-ts/utils": "0.96.1",
|
|
50
50
|
"bignumber.js": "9.3.1",
|
|
51
51
|
"eventsource": "4.1.0",
|
|
52
|
-
"js-sdsl": "4.4.2",
|
|
53
52
|
"express": "4.19.2",
|
|
54
53
|
"pino": "10.3.1",
|
|
55
54
|
"pino-pretty": "13.1.3",
|
|
56
|
-
"yargs": "17.7.2",
|
|
57
55
|
"@rescript/runtime": "12.2.0",
|
|
58
56
|
"rescript-schema": "9.5.1",
|
|
59
57
|
"viem": "2.54.0",
|
|
@@ -68,10 +66,10 @@
|
|
|
68
66
|
"tsx": "4.21.0"
|
|
69
67
|
},
|
|
70
68
|
"optionalDependencies": {
|
|
71
|
-
"envio-linux-x64": "3.
|
|
72
|
-
"envio-linux-x64-musl": "3.
|
|
73
|
-
"envio-linux-arm64": "3.
|
|
74
|
-
"envio-darwin-x64": "3.
|
|
75
|
-
"envio-darwin-arm64": "3.
|
|
69
|
+
"envio-linux-x64": "3.13.0-rc.0",
|
|
70
|
+
"envio-linux-x64-musl": "3.13.0-rc.0",
|
|
71
|
+
"envio-linux-arm64": "3.13.0-rc.0",
|
|
72
|
+
"envio-darwin-x64": "3.13.0-rc.0",
|
|
73
|
+
"envio-darwin-arm64": "3.13.0-rc.0"
|
|
76
74
|
}
|
|
77
75
|
}
|
package/src/BatchProcessing.res
CHANGED
|
@@ -69,18 +69,15 @@ and processNextBatch = async (state: IndexerState.t, ~scheduleFetch): unit => {
|
|
|
69
69
|
let isInReorgThresholdBeforeUpdate = state->IndexerState.isInReorgThreshold
|
|
70
70
|
let isRealtimeBeforeUpdate = state->IndexerState.isRealtime
|
|
71
71
|
|
|
72
|
-
let batch =
|
|
72
|
+
let batch =
|
|
73
|
+
state->IndexerState.createBatch(~batchSizeTarget=(state->IndexerState.config).batchSize)
|
|
73
74
|
|
|
74
75
|
let progressedChainsById = batch.progressedChainsById
|
|
75
76
|
|
|
76
77
|
let isBelowReorgThreshold =
|
|
77
78
|
!isInReorgThresholdBeforeUpdate && (state->IndexerState.config).shouldRollbackOnReorg
|
|
78
79
|
let shouldEnterReorgThreshold =
|
|
79
|
-
isBelowReorgThreshold &&
|
|
80
|
-
state
|
|
81
|
-
->IndexerState.chainStates
|
|
82
|
-
->Dict.valuesToArray
|
|
83
|
-
->Array.every(cs => cs->ChainState.isReadyToEnterReorgThresholdAfterBatch(~batch))
|
|
80
|
+
isBelowReorgThreshold && state->IndexerState.isReadyToEnterReorgThreshold(~batch)
|
|
84
81
|
|
|
85
82
|
if shouldEnterReorgThreshold {
|
|
86
83
|
IndexerState.enterReorgThreshold(state)
|
|
@@ -95,7 +92,7 @@ and processNextBatch = async (state: IndexerState.t, ~scheduleFetch): unit => {
|
|
|
95
92
|
// finalizing resumes exactly here: it still owes the schema its deferred
|
|
96
93
|
// indexes, and no batch will ever come along to notice.
|
|
97
94
|
state->IndexerState.markCaughtUpIfSettled
|
|
98
|
-
if state->IndexerState.
|
|
95
|
+
if state->IndexerState.shouldFinalizeIndexes {
|
|
99
96
|
await FinalizeBackfill.run(state)
|
|
100
97
|
}
|
|
101
98
|
|
|
@@ -109,9 +106,9 @@ and processNextBatch = async (state: IndexerState.t, ~scheduleFetch): unit => {
|
|
|
109
106
|
}
|
|
110
107
|
|
|
111
108
|
// When resuming from persisted state, all events may already be processed.
|
|
109
|
+
state->IndexerState.reportFinished
|
|
112
110
|
if EventProcessing.allChainsEventsProcessedToEndblock(state->IndexerState.chainStates) {
|
|
113
|
-
|
|
114
|
-
if !(state->IndexerState.keepProcessAlive) {
|
|
111
|
+
if !(state->IndexerState.keepProcessAlive) && !(state->IndexerState.isHoldingRealtime) {
|
|
115
112
|
await ExitOnCaughtUp.run(state)
|
|
116
113
|
}
|
|
117
114
|
}
|
|
@@ -162,11 +159,14 @@ and processNextBatch = async (state: IndexerState.t, ~scheduleFetch): unit => {
|
|
|
162
159
|
// Can safely reset rollback state, since overwrite is not possible.
|
|
163
160
|
state->IndexerState.clearRollback
|
|
164
161
|
state->IndexerState.applyBatchProgress(~batch)
|
|
162
|
+
// Before the finalize below, so a chain says where it finished ahead of
|
|
163
|
+
// the process saying what it does about that.
|
|
164
|
+
state->IndexerState.reportFinished
|
|
165
165
|
|
|
166
166
|
// Backfilling → FinalizingIndexes → Ready. Awaiting here holds the
|
|
167
167
|
// processing loop for the whole finalize, which is what pauses
|
|
168
168
|
// processing while the indexes are built.
|
|
169
|
-
if state->IndexerState.
|
|
169
|
+
if state->IndexerState.shouldFinalizeIndexes {
|
|
170
170
|
await FinalizeBackfill.run(state)
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -182,11 +182,12 @@ and processNextBatch = async (state: IndexerState.t, ~scheduleFetch): unit => {
|
|
|
182
182
|
let allCaughtUp = EventProcessing.allChainsEventsProcessedToEndblock(
|
|
183
183
|
state->IndexerState.chainStates,
|
|
184
184
|
)
|
|
185
|
-
if allCaughtUp {
|
|
186
|
-
Logging.info("All chains are caught up to end blocks.")
|
|
187
|
-
}
|
|
188
185
|
|
|
189
|
-
if
|
|
186
|
+
if (
|
|
187
|
+
allCaughtUp &&
|
|
188
|
+
!(state->IndexerState.keepProcessAlive) &&
|
|
189
|
+
!(state->IndexerState.isHoldingRealtime)
|
|
190
|
+
) {
|
|
190
191
|
await ExitOnCaughtUp.run(state)
|
|
191
192
|
} else if (
|
|
192
193
|
// In auto-exit mode, error if all chains reached head with no events found
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as Logging from "./Logging.res.mjs";
|
|
5
4
|
import * as ChainState from "./ChainState.res.mjs";
|
|
6
5
|
import * as IndexerState from "./IndexerState.res.mjs";
|
|
7
6
|
import * as ChainMetadata from "./ChainMetadata.res.mjs";
|
|
@@ -26,7 +25,7 @@ async function processNextBatch(state, scheduleFetch) {
|
|
|
26
25
|
let batch = IndexerState.createBatch(state, IndexerState.config(state).batchSize);
|
|
27
26
|
let progressedChainsById = batch.progressedChainsById;
|
|
28
27
|
let isBelowReorgThreshold = !isInReorgThresholdBeforeUpdate && IndexerState.config(state).shouldRollbackOnReorg;
|
|
29
|
-
let shouldEnterReorgThreshold = isBelowReorgThreshold &&
|
|
28
|
+
let shouldEnterReorgThreshold = isBelowReorgThreshold && IndexerState.isReadyToEnterReorgThreshold(state, batch);
|
|
30
29
|
if (shouldEnterReorgThreshold) {
|
|
31
30
|
IndexerState.enterReorgThreshold(state);
|
|
32
31
|
}
|
|
@@ -35,20 +34,16 @@ async function processNextBatch(state, scheduleFetch) {
|
|
|
35
34
|
scheduleFetch();
|
|
36
35
|
}
|
|
37
36
|
IndexerState.markCaughtUpIfSettled(state);
|
|
38
|
-
if (IndexerState.
|
|
37
|
+
if (IndexerState.shouldFinalizeIndexes(state)) {
|
|
39
38
|
await FinalizeBackfill.run(state);
|
|
40
39
|
}
|
|
41
40
|
if (!isRealtimeBeforeUpdate && IndexerState.isRealtime(state)) {
|
|
42
41
|
IndexerState.invalidateInflight(state);
|
|
43
42
|
scheduleFetch();
|
|
44
43
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return await ExitOnCaughtUp.run(state);
|
|
49
|
-
} else {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
44
|
+
IndexerState.reportFinished(state);
|
|
45
|
+
if (EventProcessing.allChainsEventsProcessedToEndblock(IndexerState.chainStates(state)) && !IndexerState.keepProcessAlive(state) && !IndexerState.isHoldingRealtime(state)) {
|
|
46
|
+
return await ExitOnCaughtUp.run(state);
|
|
52
47
|
} else {
|
|
53
48
|
return;
|
|
54
49
|
}
|
|
@@ -70,7 +65,8 @@ async function processNextBatch(state, scheduleFetch) {
|
|
|
70
65
|
}
|
|
71
66
|
IndexerState.clearRollback(state);
|
|
72
67
|
IndexerState.applyBatchProgress(state, batch);
|
|
73
|
-
|
|
68
|
+
IndexerState.reportFinished(state);
|
|
69
|
+
if (IndexerState.shouldFinalizeIndexes(state)) {
|
|
74
70
|
await FinalizeBackfill.run(state);
|
|
75
71
|
}
|
|
76
72
|
if (!isRealtimeBeforeUpdate && IndexerState.isRealtime(state)) {
|
|
@@ -78,10 +74,7 @@ async function processNextBatch(state, scheduleFetch) {
|
|
|
78
74
|
scheduleFetch();
|
|
79
75
|
}
|
|
80
76
|
let allCaughtUp = EventProcessing.allChainsEventsProcessedToEndblock(IndexerState.chainStates(state));
|
|
81
|
-
if (allCaughtUp) {
|
|
82
|
-
Logging.info("All chains are caught up to end blocks.");
|
|
83
|
-
}
|
|
84
|
-
if (allCaughtUp && !IndexerState.keepProcessAlive(state)) {
|
|
77
|
+
if (allCaughtUp && !IndexerState.keepProcessAlive(state) && !IndexerState.isHoldingRealtime(state)) {
|
|
85
78
|
return await ExitOnCaughtUp.run(state);
|
|
86
79
|
} else if (!allCaughtUp && IndexerState.exitAfterFirstEventBlock(state) && Object.values(IndexerState.chainStates(state)).every(ChainState.isAtHeadWithoutEndBlock)) {
|
|
87
80
|
return IndexerState.errorExit(state, ErrorHandling.make(new Error("No events found between startBlock and chain head. Cannot auto-detect endBlock."), undefined, undefined));
|
package/src/Bin.res
CHANGED
|
@@ -51,23 +51,30 @@ let applyEnv = (env: dict<JSON.t>) =>
|
|
|
51
51
|
|
|
52
52
|
let run = async args => {
|
|
53
53
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
if Worker.isEnabled {
|
|
55
|
+
Worker.bindToSupervisor()
|
|
56
|
+
// Its working directory, its environment and the chains it drives all came
|
|
57
|
+
// with the fork, so a worker starts the same way every other process does.
|
|
58
|
+
await Main.start()
|
|
59
|
+
} else {
|
|
60
|
+
switch (await Core.runCli(args))->Null.toOption {
|
|
61
|
+
// Rust-only command (codegen / init / stop / docker / metrics / help /
|
|
62
|
+
// version / scripts) — nothing for JS to do, exit cleanly.
|
|
63
|
+
| None => ()
|
|
64
|
+
| Some(json) =>
|
|
65
|
+
switch decodeCommand(json->JSON.parseOrThrow) {
|
|
66
|
+
| Start({reset, cwd, env, config}) =>
|
|
67
|
+
Config.prime(config)
|
|
68
|
+
processChdir(cwd)
|
|
69
|
+
applyEnv(env)
|
|
70
|
+
await Main.start(~reset)
|
|
71
|
+
| Migrate({reset, config}) =>
|
|
72
|
+
Config.prime(config)
|
|
73
|
+
await Main.migrate(~reset)
|
|
74
|
+
| DropSchema({config}) =>
|
|
75
|
+
Config.prime(config)
|
|
76
|
+
await Main.dropSchema()
|
|
77
|
+
}
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
80
|
} catch {
|
package/src/Bin.res.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import * as Core from "./Core.res.mjs";
|
|
|
4
4
|
import * as Main from "./Main.res.mjs";
|
|
5
5
|
import * as Utils from "./Utils.res.mjs";
|
|
6
6
|
import * as Config from "./Config.res.mjs";
|
|
7
|
+
import * as Worker from "./Worker.res.mjs";
|
|
7
8
|
import * as Logging from "./Logging.res.mjs";
|
|
8
9
|
import * as Process from "process";
|
|
9
10
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
@@ -57,6 +58,10 @@ function applyEnv(env) {
|
|
|
57
58
|
|
|
58
59
|
async function run(args) {
|
|
59
60
|
try {
|
|
61
|
+
if (Worker.isEnabled) {
|
|
62
|
+
Worker.bindToSupervisor();
|
|
63
|
+
return await Main.start(undefined, undefined, undefined, undefined, undefined);
|
|
64
|
+
}
|
|
60
65
|
let json = await Core.runCli(args);
|
|
61
66
|
if (json === null) {
|
|
62
67
|
return;
|
package/src/ChainFetching.res
CHANGED
|
@@ -12,16 +12,16 @@ let runContractRegistersOrThrow = async (
|
|
|
12
12
|
~itemsWithContractRegister: array<Internal.item>,
|
|
13
13
|
~config: Config.t,
|
|
14
14
|
~chainState: ChainState.t,
|
|
15
|
-
~transactionStore: option<TransactionStore.t>,
|
|
16
15
|
) => {
|
|
17
16
|
// contractRegister handlers can read event.transaction and event.block, so
|
|
18
17
|
// materialise the selected fields onto the payloads before running them. All
|
|
19
|
-
// items belong to the chain being fetched
|
|
20
|
-
//
|
|
18
|
+
// items belong to the chain being fetched, and both stores are the chain's
|
|
19
|
+
// own, which this response's pages have already been merged into.
|
|
21
20
|
await ChainState.materializePageItems(
|
|
22
21
|
~items=itemsWithContractRegister,
|
|
23
|
-
~transactionStore,
|
|
22
|
+
~transactionStore=chainState->ChainState.transactionStore,
|
|
24
23
|
~blockStore=chainState->ChainState.blockStore,
|
|
24
|
+
~shouldChecksum=chainState->ChainState.shouldChecksum,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
let registrations: array<AddressStore.registration> = []
|
|
@@ -113,14 +113,13 @@ let rec onQueryResponse = async (
|
|
|
113
113
|
latestFetchedBlockNumber,
|
|
114
114
|
stats,
|
|
115
115
|
knownHeight,
|
|
116
|
-
fromBlockQueried,
|
|
117
116
|
} = response
|
|
118
117
|
|
|
119
118
|
chainState->ChainState.recordBlockRangeFetch(
|
|
120
119
|
~totalTimeElapsed=stats.totalTimeElapsed,
|
|
121
120
|
~parsingTimeElapsed=stats.parsingTimeElapsed->Option.getOr(0.),
|
|
122
121
|
~numEvents=parsedQueueItems->Array.length,
|
|
123
|
-
~blockRangeSize=latestFetchedBlockNumber -
|
|
122
|
+
~blockRangeSize=latestFetchedBlockNumber - query.fromBlock + 1,
|
|
124
123
|
)
|
|
125
124
|
|
|
126
125
|
let numContractRegisterEvents = parsedQueueItems->Array.reduce(0, (count, item) => {
|
|
@@ -132,7 +131,7 @@ let rec onQueryResponse = async (
|
|
|
132
131
|
"msg": "Finished querying",
|
|
133
132
|
"chainId": chainId,
|
|
134
133
|
"partitionId": query.partitionId,
|
|
135
|
-
"fromBlock":
|
|
134
|
+
"fromBlock": query.fromBlock,
|
|
136
135
|
"toBlock": latestFetchedBlockNumber,
|
|
137
136
|
"numEvents": parsedQueueItems->Array.length,
|
|
138
137
|
})
|
|
@@ -141,7 +140,7 @@ let rec onQueryResponse = async (
|
|
|
141
140
|
"msg": "Finished querying",
|
|
142
141
|
"chainId": chainId,
|
|
143
142
|
"partitionId": query.partitionId,
|
|
144
|
-
"fromBlock":
|
|
143
|
+
"fromBlock": query.fromBlock,
|
|
145
144
|
"toBlock": latestFetchedBlockNumber,
|
|
146
145
|
"numEvents": parsedQueueItems->Array.length,
|
|
147
146
|
"numContractRegisterEvents": numContractRegisterEvents,
|
|
@@ -200,7 +199,18 @@ let rec onQueryResponse = async (
|
|
|
200
199
|
// Advances synchronously to FindingReorgDepth, so a concurrent rollback
|
|
201
200
|
// kick (eg from the processing loop quiescing) collapses into this one.
|
|
202
201
|
scheduleRollback()
|
|
202
|
+
// No rollback: either the guard found no reorg, or it found one and this
|
|
203
|
+
// chain only reports them. Either way the guard has merged the blocks, so
|
|
204
|
+
// the transactions follow. A source that reads the chain store to decide
|
|
205
|
+
// what to fetch leaves out what the store already holds, so its page alone
|
|
206
|
+
// does not cover its own items — only the merged store does, and contract
|
|
207
|
+
// registers read it below.
|
|
203
208
|
| None =>
|
|
209
|
+
switch transactionStore {
|
|
210
|
+
| Some(page) => chainState->ChainState.transactionStore->TransactionStore.merge(page)
|
|
211
|
+
| None => ()
|
|
212
|
+
}
|
|
213
|
+
|
|
204
214
|
// Over-fetched events (a merged partition returning an address before its
|
|
205
215
|
// effectiveStartBlock, a wildcard param referencing an address registered
|
|
206
216
|
// after the log's block, or a registration whose own start block is later
|
|
@@ -228,7 +238,6 @@ let rec onQueryResponse = async (
|
|
|
228
238
|
~knownHeight,
|
|
229
239
|
~latestFetchedBlock=latestFetchedBlockNumber,
|
|
230
240
|
~query,
|
|
231
|
-
~transactionStore,
|
|
232
241
|
)
|
|
233
242
|
ChainMetadata.stage(state)
|
|
234
243
|
scheduleFetch()
|
|
@@ -242,7 +251,6 @@ let rec onQueryResponse = async (
|
|
|
242
251
|
~itemsWithContractRegister,
|
|
243
252
|
~config=state->IndexerState.config,
|
|
244
253
|
~chainState,
|
|
245
|
-
~transactionStore,
|
|
246
254
|
) {
|
|
247
255
|
| exception exn => IndexerState.errorExit(state, exn->ErrorHandling.make)
|
|
248
256
|
| newRegistrations => proceed(~newRegistrations)
|
|
@@ -259,10 +267,8 @@ and applyQueryResponse = (
|
|
|
259
267
|
~knownHeight,
|
|
260
268
|
~latestFetchedBlock,
|
|
261
269
|
~query,
|
|
262
|
-
~transactionStore,
|
|
263
270
|
) => {
|
|
264
271
|
let chainState = state->IndexerState.getChainState(~chainId)
|
|
265
|
-
let wasFetchingAtHead = chainState->ChainState.isFetchingAtHead
|
|
266
272
|
|
|
267
273
|
chainState->ChainState.handleQueryResult(
|
|
268
274
|
~query,
|
|
@@ -270,7 +276,6 @@ and applyQueryResponse = (
|
|
|
270
276
|
~newItems,
|
|
271
277
|
~newRegistrations,
|
|
272
278
|
~knownHeight,
|
|
273
|
-
~transactionStore,
|
|
274
279
|
)
|
|
275
280
|
|
|
276
281
|
// In auto-exit mode, set endBlock to the first event's block when events arrive.
|
|
@@ -279,17 +284,6 @@ and applyQueryResponse = (
|
|
|
279
284
|
~blockNumber=newItems->Array.getUnsafe(0)->Internal.getItemBlockNumber,
|
|
280
285
|
)
|
|
281
286
|
}
|
|
282
|
-
|
|
283
|
-
// Log the backfill→head transition once: this response brought the fetch
|
|
284
|
-
// frontier to the head. Gated on !isReady so realtime re-catch-ups (a new
|
|
285
|
-
// block arrives, gets fetched) don't spam the log after the chain is synced.
|
|
286
|
-
if (
|
|
287
|
-
!wasFetchingAtHead &&
|
|
288
|
-
!(chainState->ChainState.isReady) &&
|
|
289
|
-
chainState->ChainState.isFetchingAtHead
|
|
290
|
-
) {
|
|
291
|
-
chainState->ChainState.logger->Logging.childInfo("All events have been fetched")
|
|
292
|
-
}
|
|
293
287
|
}
|
|
294
288
|
|
|
295
289
|
let finishWaitingForNewBlock = (
|
|
@@ -13,11 +13,12 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
13
13
|
import * as ReorgDetection from "./ReorgDetection.res.mjs";
|
|
14
14
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
15
15
|
import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
|
|
16
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
16
17
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
17
18
|
import * as ContractRegisterContext from "./ContractRegisterContext.res.mjs";
|
|
18
19
|
|
|
19
|
-
async function runContractRegistersOrThrow(itemsWithContractRegister, config, chainState
|
|
20
|
-
await ChainState.materializePageItems(itemsWithContractRegister, transactionStore, ChainState.blockStore(chainState));
|
|
20
|
+
async function runContractRegistersOrThrow(itemsWithContractRegister, config, chainState) {
|
|
21
|
+
await ChainState.materializePageItems(itemsWithContractRegister, ChainState.transactionStore(chainState), ChainState.blockStore(chainState), ChainState.shouldChecksum(chainState));
|
|
21
22
|
let registrations = [];
|
|
22
23
|
let onRegister = (item, contractAddress, contractName) => {
|
|
23
24
|
registrations.push({
|
|
@@ -63,15 +64,11 @@ async function runContractRegistersOrThrow(itemsWithContractRegister, config, ch
|
|
|
63
64
|
return registrations;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
function applyQueryResponse(state, chainId, newItems, newRegistrations, knownHeight, latestFetchedBlock, query
|
|
67
|
+
function applyQueryResponse(state, chainId, newItems, newRegistrations, knownHeight, latestFetchedBlock, query) {
|
|
67
68
|
let chainState = IndexerState.getChainState(state, chainId);
|
|
68
|
-
|
|
69
|
-
ChainState.handleQueryResult(chainState, query, newItems, newRegistrations, latestFetchedBlock, knownHeight, transactionStore);
|
|
69
|
+
ChainState.handleQueryResult(chainState, query, newItems, newRegistrations, latestFetchedBlock, knownHeight);
|
|
70
70
|
if (IndexerState.exitAfterFirstEventBlock(state) && newItems.length !== 0) {
|
|
71
|
-
ChainState.setEndBlockToFirstEvent(chainState, newItems[0].blockNumber);
|
|
72
|
-
}
|
|
73
|
-
if (!wasFetchingAtHead && !ChainState.isReady(chainState) && ChainState.isFetchingAtHead(chainState)) {
|
|
74
|
-
return Logging.childInfo(ChainState.logger(chainState), "All events have been fetched");
|
|
71
|
+
return ChainState.setEndBlockToFirstEvent(chainState, newItems[0].blockNumber);
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
74
|
|
|
@@ -85,11 +82,10 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
85
82
|
let chainState = IndexerState.getChainState(state, chainId);
|
|
86
83
|
let stats = response.stats;
|
|
87
84
|
let latestFetchedBlockNumber = response.latestFetchedBlockNumber;
|
|
88
|
-
let fromBlockQueried = response.fromBlockQueried;
|
|
89
85
|
let transactionStore = response.transactionStore;
|
|
90
86
|
let parsedQueueItems = response.parsedQueueItems;
|
|
91
87
|
let knownHeight = response.knownHeight;
|
|
92
|
-
ChainState.recordBlockRangeFetch(chainState, stats["total time elapsed (s)"], Stdlib_Option.getOr(stats["parsing time (s)"], 0), parsedQueueItems.length, (latestFetchedBlockNumber -
|
|
88
|
+
ChainState.recordBlockRangeFetch(chainState, stats["total time elapsed (s)"], Stdlib_Option.getOr(stats["parsing time (s)"], 0), parsedQueueItems.length, (latestFetchedBlockNumber - query.fromBlock | 0) + 1 | 0);
|
|
93
89
|
let numContractRegisterEvents = Stdlib_Array.reduce(parsedQueueItems, 0, (count, item) => {
|
|
94
90
|
if (item.onEventRegistration.contractRegister !== undefined) {
|
|
95
91
|
return count + 1 | 0;
|
|
@@ -102,7 +98,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
102
98
|
msg: "Finished querying",
|
|
103
99
|
chainId: chainId,
|
|
104
100
|
partitionId: query.partitionId,
|
|
105
|
-
fromBlock:
|
|
101
|
+
fromBlock: query.fromBlock,
|
|
106
102
|
toBlock: latestFetchedBlockNumber,
|
|
107
103
|
numEvents: parsedQueueItems.length
|
|
108
104
|
});
|
|
@@ -111,7 +107,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
111
107
|
msg: "Finished querying",
|
|
112
108
|
chainId: chainId,
|
|
113
109
|
partitionId: query.partitionId,
|
|
114
|
-
fromBlock:
|
|
110
|
+
fromBlock: query.fromBlock,
|
|
115
111
|
toBlock: latestFetchedBlockNumber,
|
|
116
112
|
numEvents: parsedQueueItems.length,
|
|
117
113
|
numContractRegisterEvents: numContractRegisterEvents
|
|
@@ -135,6 +131,9 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
135
131
|
IndexerState.beginReorg(state, chainId, rollbackWithReorgDetectedBlockNumber);
|
|
136
132
|
return scheduleRollback();
|
|
137
133
|
}
|
|
134
|
+
if (transactionStore !== undefined) {
|
|
135
|
+
ChainState.transactionStore(chainState).merge(Primitive_option.valFromOption(transactionStore));
|
|
136
|
+
}
|
|
138
137
|
let itemsWithContractRegister = [];
|
|
139
138
|
for (let idx = 0, idx_finish = parsedQueueItems.length; idx < idx_finish; ++idx) {
|
|
140
139
|
let item = parsedQueueItems[idx];
|
|
@@ -144,7 +143,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
144
143
|
}
|
|
145
144
|
let proceed = newRegistrations => {
|
|
146
145
|
if (!IndexerState.isStale(state, stateId)) {
|
|
147
|
-
applyQueryResponse(state, chainId, parsedQueueItems, newRegistrations, knownHeight, latestFetchedBlockNumber, query
|
|
146
|
+
applyQueryResponse(state, chainId, parsedQueueItems, newRegistrations, knownHeight, latestFetchedBlockNumber, query);
|
|
148
147
|
ChainMetadata.stage(state);
|
|
149
148
|
scheduleFetch();
|
|
150
149
|
return scheduleProcessing();
|
|
@@ -155,7 +154,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
155
154
|
}
|
|
156
155
|
let newRegistrations;
|
|
157
156
|
try {
|
|
158
|
-
newRegistrations = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), chainState
|
|
157
|
+
newRegistrations = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), chainState);
|
|
159
158
|
} catch (raw_exn) {
|
|
160
159
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
161
160
|
return IndexerState.errorExit(state, ErrorHandling.make(exn, undefined, undefined));
|