envio 3.3.0-alpha.8 → 3.3.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/index.d.ts +19 -0
- package/licenses/CLA.md +35 -0
- package/licenses/EULA.md +67 -0
- package/licenses/LICENSE.md +45 -0
- package/licenses/README.md +35 -0
- package/package.json +9 -8
- package/src/Batch.res.mjs +1 -1
- package/src/BatchProcessing.res +0 -7
- package/src/BatchProcessing.res.mjs +1 -8
- package/src/ChainFetching.res +30 -18
- package/src/ChainFetching.res.mjs +23 -13
- package/src/ChainState.res +205 -59
- package/src/ChainState.res.mjs +130 -27
- package/src/ChainState.resi +16 -1
- package/src/Config.res +9 -5
- package/src/Config.res.mjs +2 -2
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +147 -39
- package/src/CrossChainState.res.mjs +42 -10
- package/src/EffectState.res +100 -0
- package/src/EffectState.res.mjs +74 -0
- package/src/EffectState.resi +32 -0
- package/src/Envio.res +25 -7
- package/src/Envio.res.mjs +15 -19
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +30 -56
- package/src/EventConfigBuilder.res.mjs +24 -30
- package/src/EventProcessing.res +8 -5
- package/src/EventProcessing.res.mjs +2 -1
- package/src/FetchState.res +842 -474
- package/src/FetchState.res.mjs +545 -356
- package/src/HandlerLoader.res +1 -1
- package/src/HandlerLoader.res.mjs +1 -1
- package/src/HandlerRegister.res +478 -305
- package/src/HandlerRegister.res.mjs +277 -209
- package/src/HandlerRegister.resi +11 -6
- package/src/InMemoryStore.res +14 -26
- package/src/InMemoryStore.res.mjs +6 -19
- package/src/IndexerState.res +15 -39
- package/src/IndexerState.res.mjs +18 -29
- package/src/IndexerState.resi +2 -10
- package/src/Internal.res +121 -18
- package/src/Internal.res.mjs +96 -2
- package/src/LoadLayer.res +44 -24
- package/src/LoadLayer.res.mjs +43 -20
- package/src/LoadLayer.resi +1 -0
- package/src/LogSelection.res +92 -217
- package/src/LogSelection.res.mjs +95 -184
- package/src/Main.res +29 -143
- package/src/Main.res.mjs +25 -88
- package/src/Metrics.res +1 -1
- package/src/Metrics.res.mjs +1 -1
- package/src/Persistence.res +12 -3
- package/src/PgStorage.res +155 -82
- package/src/PgStorage.res.mjs +130 -77
- package/src/Prometheus.res +20 -10
- package/src/Prometheus.res.mjs +22 -10
- package/src/PruneStaleHistory.res +146 -35
- package/src/PruneStaleHistory.res.mjs +114 -20
- package/src/RawEvent.res +2 -2
- package/src/Rollback.res +32 -13
- package/src/Rollback.res.mjs +24 -11
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +1 -1
- package/src/SimulateItems.res +39 -7
- package/src/SimulateItems.res.mjs +28 -9
- package/src/TestIndexer.res +2 -2
- package/src/TestIndexer.res.mjs +2 -2
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/UserContext.res +62 -23
- package/src/UserContext.res.mjs +26 -6
- package/src/Writing.res +60 -21
- package/src/Writing.res.mjs +27 -9
- package/src/bindings/NodeJs.res +5 -0
- package/src/bindings/Viem.res +0 -5
- package/src/sources/EventRouter.res +0 -21
- package/src/sources/EventRouter.res.mjs +0 -12
- package/src/sources/Evm.res +4 -1
- package/src/sources/Evm.res.mjs +1 -1
- package/src/sources/EvmChain.res +2 -27
- package/src/sources/EvmChain.res.mjs +2 -23
- package/src/sources/EvmRpcClient.res +58 -23
- package/src/sources/EvmRpcClient.res.mjs +11 -5
- package/src/sources/Fuel.res +3 -1
- package/src/sources/Fuel.res.mjs +1 -1
- package/src/sources/HyperSync.res +9 -38
- package/src/sources/HyperSync.res.mjs +16 -28
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +88 -11
- package/src/sources/HyperSyncClient.res.mjs +39 -6
- package/src/sources/HyperSyncSource.res +18 -210
- package/src/sources/HyperSyncSource.res.mjs +9 -137
- package/src/sources/Rpc.res +0 -32
- package/src/sources/Rpc.res.mjs +1 -46
- package/src/sources/RpcSource.res +129 -533
- package/src/sources/RpcSource.res.mjs +161 -379
- package/src/sources/SimulateSource.res +37 -19
- package/src/sources/SimulateSource.res.mjs +27 -10
- package/src/sources/SourceManager.res +4 -14
- package/src/sources/SourceManager.res.mjs +3 -9
- package/src/sources/SourceManager.resi +0 -2
- package/src/sources/SvmHyperSyncSource.res +13 -3
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
|
@@ -1,46 +1,140 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Env from "./Env.res.mjs";
|
|
3
4
|
import * as Utils from "./Utils.res.mjs";
|
|
5
|
+
import * as Config from "./Config.res.mjs";
|
|
4
6
|
import * as Logging from "./Logging.res.mjs";
|
|
5
|
-
import * as Throttler from "./Throttler.res.mjs";
|
|
6
7
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
7
8
|
import * as Performance from "./bindings/Performance.res.mjs";
|
|
8
9
|
import * as IndexerState from "./IndexerState.res.mjs";
|
|
9
|
-
import * as
|
|
10
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
11
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
let
|
|
14
|
-
|
|
13
|
+
function selectFrom(allEntities, lastPrunedAtMillis, writtenEntityNames, isRollback, nowMillis, intervalMillis, safeCheckpointId) {
|
|
14
|
+
let byOldestPrune = (param, param$1) => param[0] - param$1[0];
|
|
15
|
+
let toEntities = candidates => candidates.map(param => param[1]);
|
|
16
|
+
let concurrentCandidates = [];
|
|
17
|
+
let forcedCandidates = [];
|
|
18
|
+
allEntities.forEach(entityConfig => {
|
|
19
|
+
if (!entityConfig.storage.postgres) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let lastPrunedAt = Stdlib_Option.getOr(lastPrunedAtMillis[entityConfig.name], 0);
|
|
23
|
+
if (!isRollback && !writtenEntityNames.has(entityConfig.name) && nowMillis - lastPrunedAt >= intervalMillis) {
|
|
24
|
+
concurrentCandidates.push([
|
|
25
|
+
lastPrunedAt,
|
|
26
|
+
entityConfig
|
|
27
|
+
]);
|
|
28
|
+
return;
|
|
29
|
+
} else if (nowMillis - lastPrunedAt >= intervalMillis * 5) {
|
|
30
|
+
forcedCandidates.push([
|
|
31
|
+
lastPrunedAt,
|
|
32
|
+
entityConfig
|
|
33
|
+
]);
|
|
34
|
+
return;
|
|
35
|
+
} else {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
let sortedConcurrent = concurrentCandidates.toSorted(byOldestPrune);
|
|
40
|
+
for (let idx = 5, idx_finish = sortedConcurrent.length; idx < idx_finish; ++idx) {
|
|
41
|
+
let match = sortedConcurrent[idx];
|
|
42
|
+
if (nowMillis - match[0] >= intervalMillis * 5) {
|
|
43
|
+
forcedCandidates.push(sortedConcurrent[idx]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
safeCheckpointId: safeCheckpointId,
|
|
48
|
+
concurrent: toEntities(sortedConcurrent.slice(0, 5)),
|
|
49
|
+
forced: toEntities(forcedCandidates.toSorted(byOldestPrune).slice(0, 5))
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function select(state, writtenEntityNames, isRollback) {
|
|
54
|
+
let config = IndexerState.config(state);
|
|
55
|
+
if (!Config.shouldPruneHistory(config, IndexerState.isInReorgThreshold(state))) {
|
|
15
56
|
return;
|
|
16
57
|
}
|
|
58
|
+
let safeCheckpointId = IndexerState.getSafeCheckpointId(state);
|
|
59
|
+
if (safeCheckpointId !== undefined) {
|
|
60
|
+
return selectFrom(IndexerState.persistence(state).allEntities, IndexerState.lastPrunedAtMillis(state), writtenEntityNames, isRollback, Date.now(), Env.ThrottleWrites.pruneStaleDataIntervalMillis, safeCheckpointId);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function pruneEntities(state, entities, safeCheckpointId) {
|
|
17
65
|
let persistence = IndexerState.persistence(state);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (idx !== 0) {
|
|
21
|
-
await Utils.delay(1000);
|
|
22
|
-
}
|
|
23
|
-
let entityConfig = persistence.allEntities[idx];
|
|
66
|
+
for (let idx = 0, idx_finish = entities.length; idx < idx_finish; ++idx) {
|
|
67
|
+
let entityConfig = entities[idx];
|
|
24
68
|
let timeRef = Performance.now();
|
|
69
|
+
IndexerState.lastPrunedAtMillis(state)[entityConfig.name] = Date.now();
|
|
70
|
+
let exit = 0;
|
|
71
|
+
let val;
|
|
25
72
|
try {
|
|
26
|
-
await persistence.storage.pruneStaleEntityHistory(entityConfig.name, entityConfig.index, safeCheckpointId);
|
|
73
|
+
val = await persistence.storage.pruneStaleEntityHistory(entityConfig.name, entityConfig.index, safeCheckpointId);
|
|
74
|
+
exit = 1;
|
|
27
75
|
} catch (raw_exn) {
|
|
28
76
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
29
|
-
|
|
77
|
+
Logging.childErrorWithExn(Logging.createChild({
|
|
30
78
|
entityName: entityConfig.name,
|
|
31
79
|
safeCheckpointId: safeCheckpointId
|
|
32
|
-
}), `Failed to prune stale entity history
|
|
80
|
+
}), Utils.prettifyExn(exn), `Failed to prune stale entity history`);
|
|
81
|
+
}
|
|
82
|
+
if (exit === 1) {
|
|
83
|
+
Prometheus.RollbackHistoryPrune.increment(Performance.secondsSince(timeRef), entityConfig.name);
|
|
33
84
|
}
|
|
34
|
-
Prometheus.RollbackHistoryPrune.increment(Performance.secondsSince(timeRef), entityConfig.name);
|
|
35
85
|
}
|
|
36
86
|
}
|
|
37
87
|
|
|
38
|
-
function
|
|
39
|
-
|
|
88
|
+
async function pruneCheckpoints(state, safeCheckpointId) {
|
|
89
|
+
try {
|
|
90
|
+
await IndexerState.persistence(state).storage.pruneStaleCheckpoints(safeCheckpointId);
|
|
91
|
+
return;
|
|
92
|
+
} catch (raw_exn) {
|
|
93
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
94
|
+
return Logging.childErrorWithExn(Logging.createChild({
|
|
95
|
+
safeCheckpointId: safeCheckpointId
|
|
96
|
+
}), Utils.prettifyExn(exn), `Failed to prune stale checkpoints`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function runConcurrent(state, targets) {
|
|
101
|
+
if (targets === undefined) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
let concurrent = targets.concurrent;
|
|
105
|
+
let safeCheckpointId = targets.safeCheckpointId;
|
|
106
|
+
if (Utils.$$Array.notEmpty(concurrent)) {
|
|
107
|
+
await pruneCheckpoints(state, safeCheckpointId);
|
|
108
|
+
return await pruneEntities(state, concurrent, safeCheckpointId);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function runForced(state, targets) {
|
|
113
|
+
if (targets === undefined) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
let forced = targets.forced;
|
|
117
|
+
let safeCheckpointId = targets.safeCheckpointId;
|
|
118
|
+
if (Utils.$$Array.notEmpty(forced)) {
|
|
119
|
+
if (Utils.$$Array.isEmpty(targets.concurrent)) {
|
|
120
|
+
await pruneCheckpoints(state, safeCheckpointId);
|
|
121
|
+
}
|
|
122
|
+
return await pruneEntities(state, forced, safeCheckpointId);
|
|
123
|
+
}
|
|
40
124
|
}
|
|
41
125
|
|
|
126
|
+
let maxEntitiesPerWrite = 5;
|
|
127
|
+
|
|
128
|
+
let forcedIntervalMultiplier = 5;
|
|
129
|
+
|
|
42
130
|
export {
|
|
43
|
-
|
|
44
|
-
|
|
131
|
+
maxEntitiesPerWrite,
|
|
132
|
+
forcedIntervalMultiplier,
|
|
133
|
+
selectFrom,
|
|
134
|
+
select,
|
|
135
|
+
pruneEntities,
|
|
136
|
+
pruneCheckpoints,
|
|
137
|
+
runConcurrent,
|
|
138
|
+
runForced,
|
|
45
139
|
}
|
|
46
|
-
/*
|
|
140
|
+
/* Env Not a pure module */
|
package/src/RawEvent.res
CHANGED
|
@@ -32,8 +32,8 @@ let make = (
|
|
|
32
32
|
~blockTimestamp: int,
|
|
33
33
|
~cleanUpRawEventFieldsInPlace: JSON.t => unit,
|
|
34
34
|
): Internal.rawEvent => {
|
|
35
|
-
let {
|
|
36
|
-
let eventConfig = onEventRegistration.eventConfig
|
|
35
|
+
let {chain, blockNumber, logIndex} = eventItem
|
|
36
|
+
let eventConfig = eventItem.onEventRegistration.eventConfig
|
|
37
37
|
let chainId = chain->ChainMap.Chain.toChainId
|
|
38
38
|
let eventId = EventUtils.packEventIndex(~logIndex, ~blockNumber)
|
|
39
39
|
let blockFields =
|
package/src/Rollback.res
CHANGED
|
@@ -72,7 +72,7 @@ let rec rollback = async (
|
|
|
72
72
|
// found yet. Wait for the ReorgDetected branch above to find it and re-kick.
|
|
73
73
|
| FindingReorgDepth => ()
|
|
74
74
|
| FoundReorgDepth(_) if state->IndexerState.isProcessing =>
|
|
75
|
-
Logging.
|
|
75
|
+
Logging.trace("Waiting for batch to finish processing before executing rollback")
|
|
76
76
|
| FoundReorgDepth({chain: reorgChain, rollbackTargetBlockNumber}) =>
|
|
77
77
|
await executeRollback(
|
|
78
78
|
state,
|
|
@@ -96,10 +96,10 @@ and executeRollback = async (
|
|
|
96
96
|
) => {
|
|
97
97
|
let startTime = Performance.now()
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
// Not derived from the reorg chain's logger: that would bind its chainId onto
|
|
100
|
+
// every line, colliding with the per-chain chainId on the "Rollbacked" logs.
|
|
101
|
+
// The reorg chain is identified by the reorgChain param instead.
|
|
102
|
+
let logger = Logging.createChild(
|
|
103
103
|
~params={
|
|
104
104
|
"action": "Rollback",
|
|
105
105
|
"reorgChain": reorgChain,
|
|
@@ -161,10 +161,12 @@ and executeRollback = async (
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
let rolledBackChains = []
|
|
164
165
|
state
|
|
165
166
|
->IndexerState.chainStates
|
|
166
167
|
->Utils.Dict.forEach(cs => {
|
|
167
168
|
let chainId = (cs->ChainState.chainConfig).id
|
|
169
|
+
let fromBlock = cs->ChainState.committedProgressBlockNumber
|
|
168
170
|
cs->ChainState.rollback(
|
|
169
171
|
~newProgressBlockNumber=newProgressBlockNumberPerChain->Utils.Dict.dangerouslyGetByIntNonOption(
|
|
170
172
|
chainId,
|
|
@@ -175,6 +177,19 @@ and executeRollback = async (
|
|
|
175
177
|
~rollbackTargetBlockNumber,
|
|
176
178
|
~isReorgChain=chainId === reorgChainId,
|
|
177
179
|
)
|
|
180
|
+
let toBlock = cs->ChainState.committedProgressBlockNumber
|
|
181
|
+
if fromBlock !== toBlock {
|
|
182
|
+
rolledBackChains
|
|
183
|
+
->Array.push({
|
|
184
|
+
"chainId": chainId,
|
|
185
|
+
"fromBlock": fromBlock,
|
|
186
|
+
"toBlock": toBlock,
|
|
187
|
+
"rollbackedEvents": eventsProcessedDiffByChain
|
|
188
|
+
->Utils.Dict.dangerouslyGetByIntNonOption(chainId)
|
|
189
|
+
->Option.getOr(0.),
|
|
190
|
+
})
|
|
191
|
+
->ignore
|
|
192
|
+
}
|
|
178
193
|
})
|
|
179
194
|
|
|
180
195
|
let diff = await state->InMemoryStore.prepareRollbackDiff(
|
|
@@ -183,15 +198,19 @@ and executeRollback = async (
|
|
|
183
198
|
~progressBlockNumberByChainId=newProgressBlockNumberPerChain,
|
|
184
199
|
)
|
|
185
200
|
|
|
201
|
+
rolledBackChains->Array.forEach(chain => {
|
|
202
|
+
logger->Logging.childInfo({
|
|
203
|
+
"msg": "Rollbacked",
|
|
204
|
+
"chainId": chain["chainId"],
|
|
205
|
+
"fromBlock": chain["fromBlock"],
|
|
206
|
+
"toBlock": chain["toBlock"],
|
|
207
|
+
"rollbackedEvents": chain["rollbackedEvents"],
|
|
208
|
+
})
|
|
209
|
+
})
|
|
186
210
|
logger->Logging.childTrace({
|
|
187
|
-
"msg": "
|
|
188
|
-
"
|
|
189
|
-
|
|
190
|
-
"upserted": diff["setEntities"],
|
|
191
|
-
},
|
|
192
|
-
"rollbackedEvents": rollbackedProcessedEvents.contents,
|
|
193
|
-
"beforeCheckpointId": state->IndexerState.committedCheckpointId,
|
|
194
|
-
"targetCheckpointId": rollbackTargetCheckpointId,
|
|
211
|
+
"msg": "Rollback entity changes",
|
|
212
|
+
"deleted": diff["deletedEntities"],
|
|
213
|
+
"upserted": diff["setEntities"],
|
|
195
214
|
})
|
|
196
215
|
Prometheus.RollbackSuccess.increment(
|
|
197
216
|
~timeSeconds=Performance.secondsSince(startTime),
|
package/src/Rollback.res.mjs
CHANGED
|
@@ -33,8 +33,7 @@ async function getLastKnownValidBlock(chainState, reorgBlockNumber, isRealtime)
|
|
|
33
33
|
|
|
34
34
|
async function executeRollback(state, reorgChain, rollbackTargetBlockNumber, scheduleFetch, scheduleProcessing) {
|
|
35
35
|
let startTime = Performance.now();
|
|
36
|
-
let
|
|
37
|
-
let logger = Logging.createChildFrom(ChainState.logger(chainState), {
|
|
36
|
+
let logger = Logging.createChild({
|
|
38
37
|
action: "Rollback",
|
|
39
38
|
reorgChain: reorgChain,
|
|
40
39
|
targetBlockNumber: rollbackTargetBlockNumber
|
|
@@ -55,20 +54,34 @@ async function executeRollback(state, reorgChain, rollbackTargetBlockNumber, sch
|
|
|
55
54
|
eventsProcessedDiffByChain[diff.chain_id] = eventsProcessedDiff;
|
|
56
55
|
newProgressBlockNumberPerChain[diff.chain_id] = rollbackTargetCheckpointId === 0n && diff.chain_id === reorgChain ? Primitive_int.min(diff.new_progress_block_number, rollbackTargetBlockNumber) : diff.new_progress_block_number;
|
|
57
56
|
}
|
|
57
|
+
let rolledBackChains = [];
|
|
58
58
|
Utils.Dict.forEach(IndexerState.chainStates(state), cs => {
|
|
59
59
|
let chainId = ChainState.chainConfig(cs).id;
|
|
60
|
+
let fromBlock = ChainState.committedProgressBlockNumber(cs);
|
|
60
61
|
ChainState.rollback(cs, newProgressBlockNumberPerChain[chainId], eventsProcessedDiffByChain[chainId], rollbackTargetBlockNumber, chainId === reorgChain);
|
|
62
|
+
let toBlock = ChainState.committedProgressBlockNumber(cs);
|
|
63
|
+
if (fromBlock !== toBlock) {
|
|
64
|
+
rolledBackChains.push({
|
|
65
|
+
chainId: chainId,
|
|
66
|
+
fromBlock: fromBlock,
|
|
67
|
+
toBlock: toBlock,
|
|
68
|
+
rollbackedEvents: Stdlib_Option.getOr(eventsProcessedDiffByChain[chainId], 0)
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
61
72
|
});
|
|
62
73
|
let diff$1 = await InMemoryStore.prepareRollbackDiff(state, rollbackTargetCheckpointId, IndexerState.committedCheckpointId(state) + 1n, newProgressBlockNumberPerChain);
|
|
74
|
+
rolledBackChains.forEach(chain => Logging.childInfo(logger, {
|
|
75
|
+
msg: "Rollbacked",
|
|
76
|
+
chainId: chain.chainId,
|
|
77
|
+
fromBlock: chain.fromBlock,
|
|
78
|
+
toBlock: chain.toBlock,
|
|
79
|
+
rollbackedEvents: chain.rollbackedEvents
|
|
80
|
+
}));
|
|
63
81
|
Logging.childTrace(logger, {
|
|
64
|
-
msg: "
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
upserted: diff$1.setEntities
|
|
68
|
-
},
|
|
69
|
-
rollbackedEvents: rollbackedProcessedEvents,
|
|
70
|
-
beforeCheckpointId: IndexerState.committedCheckpointId(state),
|
|
71
|
-
targetCheckpointId: rollbackTargetCheckpointId
|
|
82
|
+
msg: "Rollback entity changes",
|
|
83
|
+
deleted: diff$1.deletedEntities,
|
|
84
|
+
upserted: diff$1.setEntities
|
|
72
85
|
});
|
|
73
86
|
Prometheus.RollbackSuccess.increment(Performance.secondsSince(startTime), rollbackedProcessedEvents);
|
|
74
87
|
IndexerState.completeRollback(state, eventsProcessedDiffByChain);
|
|
@@ -97,7 +110,7 @@ async function rollback(state, scheduleFetch, scheduleProcessing, scheduleRollba
|
|
|
97
110
|
return scheduleRollback();
|
|
98
111
|
case "FoundReorgDepth" :
|
|
99
112
|
if (IndexerState.isProcessing(state)) {
|
|
100
|
-
return Logging.
|
|
113
|
+
return Logging.trace("Waiting for batch to finish processing before executing rollback");
|
|
101
114
|
} else {
|
|
102
115
|
return await executeRollback(state, match.chain, match.rollbackTargetBlockNumber, scheduleFetch, scheduleProcessing);
|
|
103
116
|
}
|
package/src/RollbackCommit.res
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
type args = {chainId: int, rollbackToBlock: int}
|
|
7
7
|
type callback = args => promise<unit>
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// Lives in the process-wide `EnvioGlobal` record so callbacks registered
|
|
10
|
+
// through a duplicate envio module instance still fire.
|
|
11
|
+
let callbacks =
|
|
12
|
+
EnvioGlobal.value.rollbackCommitCallbacks->(Utils.magic: array<unknown> => array<callback>)
|
|
10
13
|
|
|
11
14
|
let register = (callback: callback) => {
|
|
12
15
|
callbacks->Array.push(callback)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
4
|
+
import * as EnvioGlobal from "./EnvioGlobal.res.mjs";
|
|
4
5
|
|
|
5
|
-
let callbacks =
|
|
6
|
+
let callbacks = EnvioGlobal.value.rollbackCommitCallbacks;
|
|
6
7
|
|
|
7
8
|
function register(callback) {
|
|
8
9
|
callbacks.push(callback);
|
|
@@ -32,4 +33,4 @@ export {
|
|
|
32
33
|
register,
|
|
33
34
|
fire,
|
|
34
35
|
}
|
|
35
|
-
/*
|
|
36
|
+
/* EnvioGlobal Not a pure module */
|
|
@@ -10,7 +10,7 @@ let itemKey = (item: Internal.item): string =>
|
|
|
10
10
|
`${chain
|
|
11
11
|
->ChainMap.Chain.toChainId
|
|
12
12
|
->Int.toString}:${blockNumber->Int.toString}:${logIndex->Int.toString}`
|
|
13
|
-
| _ => ""
|
|
13
|
+
| Internal.Block(_) => ""
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// `index` is the item's position in its chain's `simulate` array, reported back
|
package/src/SimulateItems.res
CHANGED
|
@@ -240,9 +240,12 @@ let deriveSrcAddress = (
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
let parse = (
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
let parse = (
|
|
244
|
+
~simulateItems: array<JSON.t>,
|
|
245
|
+
~config: Config.t,
|
|
246
|
+
~chainConfig: Config.chain,
|
|
247
|
+
~onEventRegistrations: array<Internal.onEventRegistration>,
|
|
248
|
+
): array<Internal.item> => {
|
|
246
249
|
let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
|
|
247
250
|
let chainId = chainConfig.id
|
|
248
251
|
let startBlock = chainConfig.startBlock
|
|
@@ -336,7 +339,7 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
|
|
|
336
339
|
| None => seenCoordinates->Dict.set(coordinate, itemIndex)
|
|
337
340
|
}
|
|
338
341
|
|
|
339
|
-
// Build a real registration the same way `HandlerRegister.
|
|
342
|
+
// Build a real registration the same way `HandlerRegister.finishRegistration`
|
|
340
343
|
// does at startup (not a stub), so the address filter and `where`
|
|
341
344
|
// behave identically to real indexing — the dead-input tracker relies
|
|
342
345
|
// on `clientAddressFilter` actually gating unrouted items.
|
|
@@ -345,6 +348,11 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
|
|
|
345
348
|
~chainId,
|
|
346
349
|
~eventConfig,
|
|
347
350
|
)
|
|
351
|
+
// Append into the registration array that the chain state will own and
|
|
352
|
+
// put that same registration object directly on the simulated item.
|
|
353
|
+
let onEventRegistrationIndex = onEventRegistrations->Array.length
|
|
354
|
+
let onEventRegistration = {...onEventRegistration, index: onEventRegistrationIndex}
|
|
355
|
+
onEventRegistrations->Array.push(onEventRegistration)->ignore
|
|
348
356
|
|
|
349
357
|
items
|
|
350
358
|
->Array.push(
|
|
@@ -382,7 +390,11 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
|
|
|
382
390
|
|
|
383
391
|
// Apply simulate source config from processConfig JSON to a Config.t
|
|
384
392
|
// This patches chainMap entries that have simulate items with CustomSources
|
|
385
|
-
let patchConfig = (
|
|
393
|
+
let patchConfig = (
|
|
394
|
+
~config: Config.t,
|
|
395
|
+
~processConfig: JSON.t,
|
|
396
|
+
~registrationsByChainId: HandlerRegister.registrationsByChainId,
|
|
397
|
+
): Config.t => {
|
|
386
398
|
let processChains: option<dict<JSON.t>> =
|
|
387
399
|
(processConfig->(Utils.magic: JSON.t => {..}))["chains"]->Nullable.toOption
|
|
388
400
|
switch processChains {
|
|
@@ -395,11 +407,31 @@ let patchConfig = (~config: Config.t, ~processConfig: JSON.t): Config.t => {
|
|
|
395
407
|
let simulateRaw: option<array<JSON.t>> = raw["simulate"]->Nullable.toOption
|
|
396
408
|
switch simulateRaw {
|
|
397
409
|
| Some(simulateItems) =>
|
|
398
|
-
let
|
|
410
|
+
let chainRegistrations = switch registrationsByChainId->Utils.Dict.dangerouslyGetNonOption(
|
|
411
|
+
chainIdStr,
|
|
412
|
+
) {
|
|
413
|
+
| Some(registrations) => registrations
|
|
414
|
+
| None =>
|
|
415
|
+
let registrations: HandlerRegister.chainRegistrations = {
|
|
416
|
+
onEventRegistrations: [],
|
|
417
|
+
onBlockRegistrations: [],
|
|
418
|
+
}
|
|
419
|
+
registrationsByChainId->Dict.set(chainIdStr, registrations)
|
|
420
|
+
registrations
|
|
421
|
+
}
|
|
399
422
|
let startBlock: int = raw["startBlock"]->(Utils.magic: 'a => int)
|
|
400
423
|
let endBlock: int = raw["endBlock"]->(Utils.magic: 'a => int)
|
|
424
|
+
// Parse with the process's startBlock so items default into the range
|
|
425
|
+
// the source will be queried over; the source now filters by range.
|
|
426
|
+
let chainConfig = {...chainConfig, startBlock, endBlock}
|
|
427
|
+
let items = parse(
|
|
428
|
+
~simulateItems,
|
|
429
|
+
~config,
|
|
430
|
+
~chainConfig,
|
|
431
|
+
~onEventRegistrations=chainRegistrations.onEventRegistrations,
|
|
432
|
+
)
|
|
401
433
|
let source = SimulateSource.make(~items, ~endBlock, ~chain)
|
|
402
|
-
{...chainConfig,
|
|
434
|
+
{...chainConfig, sourceConfig: Config.CustomSources([source])}
|
|
403
435
|
| None => chainConfig
|
|
404
436
|
}
|
|
405
437
|
| None => chainConfig
|
|
@@ -167,7 +167,7 @@ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig, config)
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
function parse(simulateItems, config, chainConfig) {
|
|
170
|
+
function parse(simulateItems, config, chainConfig, onEventRegistrations) {
|
|
171
171
|
let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
|
|
172
172
|
let chainId = chainConfig.id;
|
|
173
173
|
let startBlock = chainConfig.startBlock;
|
|
@@ -254,9 +254,13 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
254
254
|
seenCoordinates[coordinate] = itemIndex;
|
|
255
255
|
}
|
|
256
256
|
let onEventRegistration = HandlerRegister.buildOnEventRegistration(config, chainId, eventConfig, undefined);
|
|
257
|
+
let onEventRegistrationIndex = onEventRegistrations.length;
|
|
258
|
+
let newrecord = {...onEventRegistration};
|
|
259
|
+
newrecord.index = onEventRegistrationIndex;
|
|
260
|
+
onEventRegistrations.push(newrecord);
|
|
257
261
|
items.push({
|
|
258
262
|
kind: 0,
|
|
259
|
-
onEventRegistration:
|
|
263
|
+
onEventRegistration: newrecord,
|
|
260
264
|
chain: chain,
|
|
261
265
|
blockNumber: blockNumber,
|
|
262
266
|
logIndex: logIndex,
|
|
@@ -276,7 +280,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
276
280
|
return items;
|
|
277
281
|
}
|
|
278
282
|
|
|
279
|
-
function patchConfig(config, processConfig) {
|
|
283
|
+
function patchConfig(config, processConfig, registrationsByChainId) {
|
|
280
284
|
let processChains = processConfig.chains;
|
|
281
285
|
if (processChains == null) {
|
|
282
286
|
return config;
|
|
@@ -291,18 +295,33 @@ function patchConfig(config, processConfig) {
|
|
|
291
295
|
if (simulateRaw == null) {
|
|
292
296
|
return chainConfig;
|
|
293
297
|
}
|
|
294
|
-
let
|
|
298
|
+
let registrations = registrationsByChainId[chainIdStr];
|
|
299
|
+
let chainRegistrations;
|
|
300
|
+
if (registrations !== undefined) {
|
|
301
|
+
chainRegistrations = registrations;
|
|
302
|
+
} else {
|
|
303
|
+
let registrations_onEventRegistrations = [];
|
|
304
|
+
let registrations_onBlockRegistrations = [];
|
|
305
|
+
let registrations$1 = {
|
|
306
|
+
onEventRegistrations: registrations_onEventRegistrations,
|
|
307
|
+
onBlockRegistrations: registrations_onBlockRegistrations
|
|
308
|
+
};
|
|
309
|
+
registrationsByChainId[chainIdStr] = registrations$1;
|
|
310
|
+
chainRegistrations = registrations$1;
|
|
311
|
+
}
|
|
295
312
|
let startBlock = processChainJson.startBlock;
|
|
296
313
|
let endBlock = processChainJson.endBlock;
|
|
297
|
-
let source = SimulateSource.make(items, endBlock, chain);
|
|
298
314
|
let newrecord = {...chainConfig};
|
|
299
|
-
newrecord.
|
|
315
|
+
newrecord.endBlock = endBlock;
|
|
316
|
+
newrecord.startBlock = startBlock;
|
|
317
|
+
let items = parse(simulateRaw, config, newrecord, chainRegistrations.onEventRegistrations);
|
|
318
|
+
let source = SimulateSource.make(items, endBlock, chain);
|
|
319
|
+
let newrecord$1 = {...newrecord};
|
|
320
|
+
newrecord$1.sourceConfig = {
|
|
300
321
|
TAG: "CustomSources",
|
|
301
322
|
_0: [source]
|
|
302
323
|
};
|
|
303
|
-
newrecord
|
|
304
|
-
newrecord.startBlock = startBlock;
|
|
305
|
-
return newrecord;
|
|
324
|
+
return newrecord$1;
|
|
306
325
|
});
|
|
307
326
|
return {
|
|
308
327
|
name: config.name,
|
package/src/TestIndexer.res
CHANGED
|
@@ -863,8 +863,8 @@ let initTestWorker = () => {
|
|
|
863
863
|
| Some(_) => ()
|
|
864
864
|
}
|
|
865
865
|
|
|
866
|
-
let patchConfig = (config: Config.t,
|
|
867
|
-
let config = SimulateItems.patchConfig(~config, ~processConfig)
|
|
866
|
+
let patchConfig = (config: Config.t, registrationsByChainId) => {
|
|
867
|
+
let config = SimulateItems.patchConfig(~config, ~processConfig, ~registrationsByChainId)
|
|
868
868
|
|
|
869
869
|
// In auto-exit mode, set batchSize=1 to process one block checkpoint at a time
|
|
870
870
|
if exitAfterFirstEventBlock {
|
package/src/TestIndexer.res.mjs
CHANGED
|
@@ -612,8 +612,8 @@ function initTestWorker() {
|
|
|
612
612
|
} else {
|
|
613
613
|
Logging.setLogLevel("silent");
|
|
614
614
|
}
|
|
615
|
-
let patchConfig = (config,
|
|
616
|
-
let config$1 = SimulateItems.patchConfig(config, processConfig);
|
|
615
|
+
let patchConfig = (config, registrationsByChainId) => {
|
|
616
|
+
let config$1 = SimulateItems.patchConfig(config, processConfig, registrationsByChainId);
|
|
617
617
|
if (exitAfterFirstEventBlock) {
|
|
618
618
|
return {
|
|
619
619
|
name: config$1.name,
|
package/src/TopicFilter.res
CHANGED
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
let toTwosComplement = (num: bigint, ~bytesLen: int) => {
|
|
2
|
-
let maxValue = 1n->BigInt.shiftLeft(BigInt.fromInt(bytesLen * 8))
|
|
3
|
-
let mask = maxValue->BigInt.sub(1n)
|
|
4
|
-
num->BigInt.add(maxValue)->BigInt.bitwiseAnd(mask)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
let fromSignedBigInt = val => {
|
|
8
|
-
let bytesLen = 32
|
|
9
|
-
let val = val >= 0n ? val : val->toTwosComplement(~bytesLen)
|
|
10
|
-
val->Viem.bigintToHex(~options={size: bytesLen})
|
|
11
|
-
}
|
|
12
|
-
|
|
13
1
|
type hex = EvmTypes.Hex.t
|
|
14
|
-
|
|
15
|
-
type bytesHex = string
|
|
16
|
-
let keccak256 = Viem.keccak256
|
|
17
|
-
let bytesToHex = Viem.bytesToHex
|
|
18
|
-
let concat = Viem.concat
|
|
19
|
-
let castToHexUnsafe: 'a => hex = val => val->(Utils.magic: 'a => hex)
|
|
20
|
-
let fromBigInt: bigint => hex = val => val->Viem.bigintToHex(~options={size: 32})
|
|
21
|
-
let fromDynamicString: string => hex = val => val->(Utils.magic: string => hex)->keccak256
|
|
22
|
-
let fromString: string => hex = val => val->Viem.stringToHex(~options={size: 32})
|
|
2
|
+
|
|
23
3
|
let fromAddress: Address.t => hex = addr => addr->(Utils.magic: Address.t => hex)->Viem.pad
|
|
24
|
-
let fromDynamicBytes: bytesHex => hex = bytes => bytes->(Utils.magic: bytesHex => hex)->keccak256
|
|
25
|
-
let fromBytes: bytesHex => hex = bytes =>
|
|
26
|
-
bytes->(Utils.magic: bytesHex => Uint8Array.t)->Viem.bytesToHex(~options={size: 32})
|
|
27
|
-
let fromBool: bool => hex = b => b->Viem.boolToHex(~options={size: 32})
|
package/src/TopicFilter.res.mjs
CHANGED
|
@@ -1,86 +1,12 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Viem from "viem";
|
|
4
|
-
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
5
|
-
|
|
6
|
-
function toTwosComplement(num, bytesLen) {
|
|
7
|
-
let maxValue = (1n << BigInt((bytesLen << 3)));
|
|
8
|
-
let mask = maxValue - 1n;
|
|
9
|
-
return num + maxValue & mask;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function fromSignedBigInt(val) {
|
|
13
|
-
let val$1 = val >= 0n ? val : toTwosComplement(val, 32);
|
|
14
|
-
return Viem.numberToHex(val$1, {
|
|
15
|
-
size: 32
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function keccak256(prim) {
|
|
20
|
-
return Viem.keccak256(prim);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function bytesToHex(prim0, prim1) {
|
|
24
|
-
return Viem.bytesToHex(prim0, prim1 !== undefined ? Primitive_option.valFromOption(prim1) : undefined);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function concat(prim) {
|
|
28
|
-
return Viem.concat(prim);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function castToHexUnsafe(val) {
|
|
32
|
-
return val;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function fromBigInt(val) {
|
|
36
|
-
return Viem.numberToHex(val, {
|
|
37
|
-
size: 32
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function fromDynamicString(val) {
|
|
42
|
-
return Viem.keccak256(val);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function fromString(val) {
|
|
46
|
-
return Viem.stringToHex(val, {
|
|
47
|
-
size: 32
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
4
|
|
|
51
5
|
function fromAddress(addr) {
|
|
52
6
|
return Viem.pad(addr);
|
|
53
7
|
}
|
|
54
8
|
|
|
55
|
-
function fromDynamicBytes(bytes) {
|
|
56
|
-
return Viem.keccak256(bytes);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function fromBytes(bytes) {
|
|
60
|
-
return Viem.bytesToHex(bytes, {
|
|
61
|
-
size: 32
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function fromBool(b) {
|
|
66
|
-
return Viem.boolToHex(b, {
|
|
67
|
-
size: 32
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
9
|
export {
|
|
72
|
-
toTwosComplement,
|
|
73
|
-
fromSignedBigInt,
|
|
74
|
-
keccak256,
|
|
75
|
-
bytesToHex,
|
|
76
|
-
concat,
|
|
77
|
-
castToHexUnsafe,
|
|
78
|
-
fromBigInt,
|
|
79
|
-
fromDynamicString,
|
|
80
|
-
fromString,
|
|
81
10
|
fromAddress,
|
|
82
|
-
fromDynamicBytes,
|
|
83
|
-
fromBytes,
|
|
84
|
-
fromBool,
|
|
85
11
|
}
|
|
86
12
|
/* viem Not a pure module */
|