envio 3.2.1 → 3.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -7
- package/src/Batch.res +12 -15
- package/src/Batch.res.mjs +4 -5
- package/src/BatchProcessing.res +199 -0
- package/src/BatchProcessing.res.mjs +125 -0
- package/src/ChainFetching.res +373 -0
- package/src/ChainFetching.res.mjs +206 -0
- package/src/ChainMetadata.res +27 -0
- package/src/ChainMetadata.res.mjs +27 -0
- package/src/ChainState.res +643 -0
- package/src/ChainState.res.mjs +476 -0
- package/src/ChainState.resi +87 -0
- package/src/Config.res +13 -4
- package/src/Config.res.mjs +8 -3
- package/src/ContractRegisterContext.res +106 -0
- package/src/ContractRegisterContext.res.mjs +76 -0
- package/src/Core.res +3 -0
- package/src/CrossChainState.res +294 -0
- package/src/CrossChainState.res.mjs +221 -0
- package/src/CrossChainState.resi +39 -0
- package/src/Ecosystem.res +58 -0
- package/src/Ecosystem.res.mjs +43 -1
- package/src/Env.res +0 -2
- package/src/Env.res.mjs +0 -3
- package/src/EventConfigBuilder.res +2 -2
- package/src/EventProcessing.res +60 -46
- package/src/EventProcessing.res.mjs +33 -32
- package/src/EventUtils.res +0 -4
- package/src/EventUtils.res.mjs +0 -4
- package/src/ExitOnCaughtUp.res +10 -0
- package/src/ExitOnCaughtUp.res.mjs +22 -0
- package/src/FetchState.res +205 -73
- package/src/FetchState.res.mjs +242 -103
- package/src/InMemoryStore.res +36 -451
- package/src/InMemoryStore.res.mjs +20 -369
- package/src/IndexerLoop.res +43 -0
- package/src/IndexerLoop.res.mjs +46 -0
- package/src/IndexerState.res +536 -0
- package/src/IndexerState.res.mjs +543 -0
- package/src/IndexerState.resi +128 -0
- package/src/Internal.res +29 -8
- package/src/LoadLayer.res +20 -18
- package/src/LoadLayer.res.mjs +14 -12
- package/src/LoadLayer.resi +6 -3
- package/src/Logging.res +11 -44
- package/src/Logging.res.mjs +10 -42
- package/src/Main.res +54 -79
- package/src/Main.res.mjs +44 -56
- package/src/PgStorage.res +8 -71
- package/src/PgStorage.res.mjs +3 -47
- package/src/Prometheus.res +1 -13
- package/src/Prometheus.res.mjs +84 -96
- package/src/PruneStaleHistory.res +45 -0
- package/src/PruneStaleHistory.res.mjs +46 -0
- package/src/RawEvent.res +73 -0
- package/src/RawEvent.res.mjs +51 -0
- package/src/Rollback.res +204 -0
- package/src/Rollback.res.mjs +118 -0
- package/src/SimulateItems.res +12 -10
- package/src/SimulateItems.res.mjs +1 -1
- package/src/UserContext.res +26 -114
- package/src/UserContext.res.mjs +15 -78
- package/src/Writing.res +242 -0
- package/src/Writing.res.mjs +215 -0
- package/src/db/InternalTable.res +14 -27
- package/src/sources/Evm.res +40 -1
- package/src/sources/Evm.res.mjs +94 -84
- package/src/sources/Fuel.res +40 -1
- package/src/sources/Fuel.res.mjs +36 -26
- package/src/sources/HyperFuel.res +41 -120
- package/src/sources/HyperFuel.res.mjs +42 -80
- package/src/sources/HyperFuel.resi +1 -24
- package/src/sources/HyperFuelClient.res +16 -297
- package/src/sources/HyperFuelClient.res.mjs +5 -4
- package/src/sources/HyperFuelSource.res +33 -8
- package/src/sources/HyperFuelSource.res.mjs +56 -10
- package/src/sources/HyperSyncSource.res +5 -3
- package/src/sources/HyperSyncSource.res.mjs +1 -1
- package/src/sources/RpcSource.res +2 -2
- package/src/sources/RpcSource.res.mjs +1 -1
- package/src/sources/SourceManager.res +14 -23
- package/src/sources/SourceManager.res.mjs +27 -29
- package/src/sources/SourceManager.resi +4 -2
- package/src/sources/Svm.res +18 -1
- package/src/sources/Svm.res.mjs +30 -22
- package/src/sources/SvmHyperSyncSource.res +1 -1
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/src/tui/Tui.res +38 -36
- package/src/tui/Tui.res.mjs +51 -51
- package/src/ChainFetcher.res +0 -519
- package/src/ChainFetcher.res.mjs +0 -314
- package/src/ChainManager.res +0 -358
- package/src/ChainManager.res.mjs +0 -291
- package/src/Ctx.res +0 -6
- package/src/Ctx.res.mjs +0 -2
- package/src/GlobalState.res +0 -1056
- package/src/GlobalState.res.mjs +0 -1086
- package/src/GlobalStateManager.res +0 -57
- package/src/GlobalStateManager.res.mjs +0 -68
- package/src/GlobalStateManager.resi +0 -7
- package/src/Ports.res +0 -5
- package/src/Ports.res.mjs +0 -9
- package/src/adapters/MarkBatchProcessedAdapter.res +0 -5
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +0 -14
- package/src/sources/EnvioApiClient.res +0 -15
- package/src/sources/EnvioApiClient.res.mjs +0 -24
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Env from "./Env.res.mjs";
|
|
4
|
+
import * as Batch from "./Batch.res.mjs";
|
|
5
|
+
import * as Utils from "./Utils.res.mjs";
|
|
6
|
+
import * as Logging from "./Logging.res.mjs";
|
|
7
|
+
import * as ChainMap from "./ChainMap.res.mjs";
|
|
8
|
+
import * as ChainState from "./ChainState.res.mjs";
|
|
9
|
+
import * as FetchState from "./FetchState.res.mjs";
|
|
10
|
+
import * as Prometheus from "./Prometheus.res.mjs";
|
|
11
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
12
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
13
|
+
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
14
|
+
import * as Primitive_float from "@rescript/runtime/lib/es6/Primitive_float.js";
|
|
15
|
+
import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
|
|
16
|
+
|
|
17
|
+
function calculateTargetBufferSize() {
|
|
18
|
+
if (Env.targetBufferSize !== undefined) {
|
|
19
|
+
return Env.targetBufferSize;
|
|
20
|
+
} else {
|
|
21
|
+
return 100000;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function make(chainStates, isInReorgThreshold, isRealtime, targetBufferSizeOpt) {
|
|
26
|
+
let targetBufferSize = targetBufferSizeOpt !== undefined ? targetBufferSizeOpt : (
|
|
27
|
+
Env.targetBufferSize !== undefined ? Env.targetBufferSize : 100000
|
|
28
|
+
);
|
|
29
|
+
let crossChainState = {
|
|
30
|
+
chainStates: chainStates,
|
|
31
|
+
chainIds: Object.values(chainStates).map(cs => ChainState.chainConfig(cs).id),
|
|
32
|
+
isRealtime: isRealtime,
|
|
33
|
+
isInReorgThreshold: isInReorgThreshold,
|
|
34
|
+
targetBufferSize: targetBufferSize
|
|
35
|
+
};
|
|
36
|
+
Prometheus.IndexingTargetBufferSize.set(targetBufferSize);
|
|
37
|
+
return crossChainState;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function chainStates(crossChainState) {
|
|
41
|
+
return crossChainState.chainStates;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isRealtime(crossChainState) {
|
|
45
|
+
return crossChainState.isRealtime;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isInReorgThreshold(crossChainState) {
|
|
49
|
+
return crossChainState.isInReorgThreshold;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function totalReadyCount(crossChainState) {
|
|
53
|
+
let total = 0;
|
|
54
|
+
for (let i = 0, i_finish = crossChainState.chainIds.length; i < i_finish; ++i) {
|
|
55
|
+
let cs = crossChainState.chainStates[crossChainState.chainIds[i]];
|
|
56
|
+
total = total + FetchState.bufferReadyCount(ChainState.fetchState(cs)) | 0;
|
|
57
|
+
}
|
|
58
|
+
return total;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function nextItemIsNone(crossChainState) {
|
|
62
|
+
return !Batch.hasReadyItem(Object.values(crossChainState.chainStates).map(ChainState.fetchState));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getSafeCheckpointId(crossChainState) {
|
|
66
|
+
let result;
|
|
67
|
+
for (let i = 0, i_finish = crossChainState.chainIds.length; i < i_finish; ++i) {
|
|
68
|
+
let cs = crossChainState.chainStates[crossChainState.chainIds[i]];
|
|
69
|
+
let safeCheckpointTracking = ChainState.safeCheckpointTracking(cs);
|
|
70
|
+
if (safeCheckpointTracking !== undefined) {
|
|
71
|
+
let safeCheckpointId = SafeCheckpointTracking.getSafeCheckpointId(safeCheckpointTracking, ChainState.fetchState(cs).knownHeight);
|
|
72
|
+
let current = result;
|
|
73
|
+
if (!(current !== undefined && safeCheckpointId >= current)) {
|
|
74
|
+
result = safeCheckpointId;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let id = result;
|
|
79
|
+
if (id !== undefined && id > 0n) {
|
|
80
|
+
return id;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function createBatch(crossChainState, processedCheckpointId, batchSizeTarget, isRollback) {
|
|
85
|
+
return Batch.make(processedCheckpointId + (
|
|
86
|
+
isRollback ? 1n : 0n
|
|
87
|
+
), Utils.Dict.mapValues(crossChainState.chainStates, cs => ({
|
|
88
|
+
fetchState: ChainState.fetchState(cs),
|
|
89
|
+
reorgDetection: ChainState.reorgDetection(cs),
|
|
90
|
+
progressBlockNumber: ChainState.committedProgressBlockNumber(cs),
|
|
91
|
+
sourceBlockNumber: ChainState.fetchState(cs).knownHeight,
|
|
92
|
+
totalEventsProcessed: ChainState.numEventsProcessed(cs),
|
|
93
|
+
chainConfig: ChainState.chainConfig(cs)
|
|
94
|
+
})), batchSizeTarget, crossChainState.isInReorgThreshold);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function enterReorgThreshold(crossChainState) {
|
|
98
|
+
Logging.info("Reorg threshold reached");
|
|
99
|
+
Prometheus.ReorgThreshold.set(true);
|
|
100
|
+
for (let i = 0, i_finish = crossChainState.chainIds.length; i < i_finish; ++i) {
|
|
101
|
+
ChainState.enterReorgThreshold(crossChainState.chainStates[crossChainState.chainIds[i]]);
|
|
102
|
+
}
|
|
103
|
+
crossChainState.isInReorgThreshold = true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function applyBatchProgress(crossChainState, batch) {
|
|
107
|
+
let chainIds = crossChainState.chainIds;
|
|
108
|
+
let everyChainCaughtUp = true;
|
|
109
|
+
for (let i = 0, i_finish = chainIds.length; i < i_finish; ++i) {
|
|
110
|
+
let cs = crossChainState.chainStates[chainIds[i]];
|
|
111
|
+
ChainState.applyBatchProgress(cs, batch);
|
|
112
|
+
if (!(ChainState.hasProcessedToEndblock(cs) || ChainState.isProgressAtHead(cs))) {
|
|
113
|
+
everyChainCaughtUp = false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
let indexerCaughtUp = nextItemIsNone(crossChainState) && everyChainCaughtUp;
|
|
117
|
+
let allChainsReady = true;
|
|
118
|
+
for (let i$1 = 0, i_finish$1 = chainIds.length; i$1 < i_finish$1; ++i$1) {
|
|
119
|
+
let cs$1 = crossChainState.chainStates[chainIds[i$1]];
|
|
120
|
+
if (indexerCaughtUp) {
|
|
121
|
+
ChainState.markReady(cs$1);
|
|
122
|
+
}
|
|
123
|
+
if (!ChainState.isReady(cs$1)) {
|
|
124
|
+
allChainsReady = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (allChainsReady) {
|
|
128
|
+
Prometheus.ProgressReady.setAllReady();
|
|
129
|
+
}
|
|
130
|
+
crossChainState.isRealtime = crossChainState.isRealtime || allChainsReady;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function priorityOrder(crossChainState) {
|
|
134
|
+
return Object.values(crossChainState.chainStates).toSorted((a, b) => Primitive_float.compare(FetchState.getProgressPercentage(ChainState.fetchState(a)), FetchState.getProgressPercentage(ChainState.fetchState(b))));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function totalReservedSize(crossChainState) {
|
|
138
|
+
let total = 0;
|
|
139
|
+
for (let i = 0, i_finish = crossChainState.chainIds.length; i < i_finish; ++i) {
|
|
140
|
+
let cs = crossChainState.chainStates[crossChainState.chainIds[i]];
|
|
141
|
+
total = total + ChainState.pendingBudget(cs);
|
|
142
|
+
}
|
|
143
|
+
return total;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function compareByProgress(a, b) {
|
|
147
|
+
return Primitive_float.compare(a.progress, b.progress);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function checkAndFetch(crossChainState, dispatchChain) {
|
|
151
|
+
let remaining = Primitive_int.max(0, (crossChainState.targetBufferSize - totalReadyCount(crossChainState) | 0) - (totalReservedSize(crossChainState) | 0) | 0);
|
|
152
|
+
let chainIds = crossChainState.chainIds;
|
|
153
|
+
let actionByChain = {};
|
|
154
|
+
let candidates = [];
|
|
155
|
+
for (let i = 0, i_finish = chainIds.length; i < i_finish; ++i) {
|
|
156
|
+
let chainId = chainIds[i];
|
|
157
|
+
let cs = crossChainState.chainStates[chainId];
|
|
158
|
+
let fetchState = ChainState.fetchState(cs);
|
|
159
|
+
let action = FetchState.getNextQuery(fetchState, remaining, ChainState.pendingBudget(cs));
|
|
160
|
+
if (typeof action !== "object") {
|
|
161
|
+
actionByChain[chainId] = action;
|
|
162
|
+
} else {
|
|
163
|
+
actionByChain[chainId] = "NothingToQuery";
|
|
164
|
+
action._0.forEach(query => {
|
|
165
|
+
query.chainId = chainId;
|
|
166
|
+
query.progress = FetchState.getProgressPercentageAt(fetchState, query.fromBlock);
|
|
167
|
+
candidates.push(query);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
candidates.sort(compareByProgress);
|
|
172
|
+
let admittedByChain = {};
|
|
173
|
+
let running = 0;
|
|
174
|
+
let idx = 0;
|
|
175
|
+
while (running < remaining && idx < candidates.length) {
|
|
176
|
+
let query = candidates[idx];
|
|
177
|
+
Utils.Dict.push(admittedByChain, query.chainId.toString(), query);
|
|
178
|
+
running = running + query.estResponseSize;
|
|
179
|
+
idx = idx + 1 | 0;
|
|
180
|
+
};
|
|
181
|
+
Stdlib_Dict.forEachWithKey(admittedByChain, (queries, chainId) => {
|
|
182
|
+
actionByChain[chainId] = {
|
|
183
|
+
TAG: "Ready",
|
|
184
|
+
_0: queries
|
|
185
|
+
};
|
|
186
|
+
let chainId$1 = Stdlib_Int.fromString(chainId, undefined);
|
|
187
|
+
ChainState.startFetchingQueries(crossChainState.chainStates[chainId$1], queries);
|
|
188
|
+
});
|
|
189
|
+
let promises = [];
|
|
190
|
+
for (let i$1 = 0, i_finish$1 = chainIds.length; i$1 < i_finish$1; ++i$1) {
|
|
191
|
+
let chainId$1 = chainIds[i$1];
|
|
192
|
+
let action$1 = actionByChain[chainId$1];
|
|
193
|
+
if (action$1 !== undefined) {
|
|
194
|
+
let exit = 0;
|
|
195
|
+
if (typeof action$1 === "object" || action$1 === "WaitingForNewBlock") {
|
|
196
|
+
exit = 1;
|
|
197
|
+
}
|
|
198
|
+
if (exit === 1) {
|
|
199
|
+
let chain = ChainMap.Chain.makeUnsafe(chainId$1);
|
|
200
|
+
promises.push(dispatchChain(chain, action$1));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
await Promise.all(promises);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
calculateTargetBufferSize,
|
|
209
|
+
make,
|
|
210
|
+
chainStates,
|
|
211
|
+
isRealtime,
|
|
212
|
+
isInReorgThreshold,
|
|
213
|
+
nextItemIsNone,
|
|
214
|
+
getSafeCheckpointId,
|
|
215
|
+
createBatch,
|
|
216
|
+
enterReorgThreshold,
|
|
217
|
+
applyBatchProgress,
|
|
218
|
+
priorityOrder,
|
|
219
|
+
checkAndFetch,
|
|
220
|
+
}
|
|
221
|
+
/* Env Not a pure module */
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Whole-indexer view over every chain's ChainState. `t` is opaque: other modules
|
|
2
|
+
// read it through the accessors and change it only through the transitions here.
|
|
3
|
+
|
|
4
|
+
type t
|
|
5
|
+
|
|
6
|
+
let calculateTargetBufferSize: unit => int
|
|
7
|
+
|
|
8
|
+
let make: (
|
|
9
|
+
~chainStates: dict<ChainState.t>,
|
|
10
|
+
~isInReorgThreshold: bool,
|
|
11
|
+
~isRealtime: bool,
|
|
12
|
+
~targetBufferSize: int=?,
|
|
13
|
+
) => t
|
|
14
|
+
|
|
15
|
+
// Accessors.
|
|
16
|
+
let chainStates: t => dict<ChainState.t>
|
|
17
|
+
let isRealtime: t => bool
|
|
18
|
+
let isInReorgThreshold: t => bool
|
|
19
|
+
|
|
20
|
+
// Derived (pure).
|
|
21
|
+
let nextItemIsNone: t => bool
|
|
22
|
+
let getSafeCheckpointId: t => option<Internal.checkpointId>
|
|
23
|
+
|
|
24
|
+
// Cross-chain transitions.
|
|
25
|
+
let createBatch: (
|
|
26
|
+
t,
|
|
27
|
+
~processedCheckpointId: Internal.checkpointId,
|
|
28
|
+
~batchSizeTarget: int,
|
|
29
|
+
~isRollback: bool,
|
|
30
|
+
) => Batch.t
|
|
31
|
+
let enterReorgThreshold: t => unit
|
|
32
|
+
let applyBatchProgress: (t, ~batch: Batch.t) => unit
|
|
33
|
+
|
|
34
|
+
// Fetch control.
|
|
35
|
+
let priorityOrder: t => array<ChainState.t>
|
|
36
|
+
let checkAndFetch: (
|
|
37
|
+
t,
|
|
38
|
+
~dispatchChain: (~chain: ChainMap.Chain.t, ~action: FetchState.nextQuery) => promise<unit>,
|
|
39
|
+
) => promise<unit>
|
package/src/Ecosystem.res
CHANGED
|
@@ -29,8 +29,66 @@ type t = {
|
|
|
29
29
|
`LogSelection.res`. SVM does not support event handlers, so its
|
|
30
30
|
schema always surfaces `None`. */
|
|
31
31
|
onEventBlockFilterSchema: S.t<option<unknown>>,
|
|
32
|
+
/** Base logger injected at construction. Used to build per-item child
|
|
33
|
+
loggers (see `getItemLogger`). */
|
|
34
|
+
logger: Pino.t,
|
|
35
|
+
/** Materialise the user-facing event handed to handlers and contract
|
|
36
|
+
registration from an item's opaque payload. */
|
|
37
|
+
toEvent: Internal.eventItem => Internal.event,
|
|
38
|
+
/** Build the per-item child logger for an event item, with
|
|
39
|
+
ecosystem-specific log fields (EVM/Fuel: contract/event/address; SVM:
|
|
40
|
+
program/instruction/programId). Closes over the injected logger. */
|
|
41
|
+
toEventLogger: Internal.eventItem => Pino.t,
|
|
42
|
+
/** Build a raw event row for the `raw_events` table. Unsupported on SVM,
|
|
43
|
+
where the implementation throws. */
|
|
44
|
+
toRawEvent: Internal.eventItem => Internal.rawEvent,
|
|
32
45
|
}
|
|
33
46
|
|
|
47
|
+
// The materialised event and the child logger are both memoised on the item
|
|
48
|
+
// object (an item is processed across preload + execution passes, and logged
|
|
49
|
+
// from several places). Hidden keys mirror each other.
|
|
50
|
+
let getItemEvent = {
|
|
51
|
+
let cacheKey = "_event"
|
|
52
|
+
(item: Internal.item, ~ecosystem: t): Internal.event => {
|
|
53
|
+
let cache = item->(Utils.magic: Internal.item => dict<Internal.event>)
|
|
54
|
+
switch cache->Utils.Dict.dangerouslyGetNonOption(cacheKey) {
|
|
55
|
+
| Some(event) => event
|
|
56
|
+
| None =>
|
|
57
|
+
let event = ecosystem.toEvent(item->Internal.castUnsafeEventItem)
|
|
58
|
+
cache->Dict.set(cacheKey, event)
|
|
59
|
+
event
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let getItemLogger = {
|
|
65
|
+
let cacheKey = "_logger"
|
|
66
|
+
(item: Internal.item, ~ecosystem: t): Pino.t => {
|
|
67
|
+
let cache = item->(Utils.magic: Internal.item => dict<Pino.t>)
|
|
68
|
+
switch cache->Utils.Dict.dangerouslyGetNonOption(cacheKey) {
|
|
69
|
+
| Some(logger) => logger
|
|
70
|
+
| None =>
|
|
71
|
+
let logger = switch item {
|
|
72
|
+
| Internal.Event(_) => ecosystem.toEventLogger(item->Internal.castUnsafeEventItem)
|
|
73
|
+
| Block({blockNumber, onBlockConfig}) =>
|
|
74
|
+
Logging.createChildFrom(
|
|
75
|
+
~logger=ecosystem.logger,
|
|
76
|
+
~params={
|
|
77
|
+
"onBlock": onBlockConfig.name,
|
|
78
|
+
"chainId": onBlockConfig.chainId,
|
|
79
|
+
"block": blockNumber,
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
cache->Dict.set(cacheKey, logger)
|
|
84
|
+
logger
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let getItemUserLogger = (item: Internal.item, ~ecosystem: t): Envio.logger =>
|
|
90
|
+
getItemLogger(item, ~ecosystem)->Logging.userLogger
|
|
91
|
+
|
|
34
92
|
let makeOnBlockArgs = (~blockNumber: int, ~ecosystem: t, ~context): Internal.onBlockArgs => {
|
|
35
93
|
switch ecosystem.name {
|
|
36
94
|
| Svm => {slot: blockNumber, context}
|
package/src/Ecosystem.res.mjs
CHANGED
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Logging from "./Logging.res.mjs";
|
|
3
4
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
4
5
|
|
|
6
|
+
let cacheKey = "_event";
|
|
7
|
+
|
|
8
|
+
function getItemEvent(item, ecosystem) {
|
|
9
|
+
let event = item[cacheKey];
|
|
10
|
+
if (event !== undefined) {
|
|
11
|
+
return Primitive_option.valFromOption(event);
|
|
12
|
+
}
|
|
13
|
+
let event$1 = ecosystem.toEvent(item);
|
|
14
|
+
item[cacheKey] = event$1;
|
|
15
|
+
return event$1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let cacheKey$1 = "_logger";
|
|
19
|
+
|
|
20
|
+
function getItemLogger(item, ecosystem) {
|
|
21
|
+
let logger = item[cacheKey$1];
|
|
22
|
+
if (logger !== undefined) {
|
|
23
|
+
return logger;
|
|
24
|
+
}
|
|
25
|
+
let logger$1;
|
|
26
|
+
if (item.kind === 0) {
|
|
27
|
+
logger$1 = ecosystem.toEventLogger(item);
|
|
28
|
+
} else {
|
|
29
|
+
let onBlockConfig = item.onBlockConfig;
|
|
30
|
+
logger$1 = Logging.createChildFrom(ecosystem.logger, {
|
|
31
|
+
onBlock: onBlockConfig.name,
|
|
32
|
+
chainId: onBlockConfig.chainId,
|
|
33
|
+
block: item.blockNumber
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
item[cacheKey$1] = logger$1;
|
|
37
|
+
return logger$1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getItemUserLogger(item, ecosystem) {
|
|
41
|
+
return Logging.userLogger(getItemLogger(item, ecosystem));
|
|
42
|
+
}
|
|
43
|
+
|
|
5
44
|
function makeOnBlockArgs(blockNumber, ecosystem, context) {
|
|
6
45
|
let match = ecosystem.name;
|
|
7
46
|
switch (match) {
|
|
@@ -23,6 +62,9 @@ function makeOnBlockArgs(blockNumber, ecosystem, context) {
|
|
|
23
62
|
}
|
|
24
63
|
|
|
25
64
|
export {
|
|
65
|
+
getItemEvent,
|
|
66
|
+
getItemLogger,
|
|
67
|
+
getItemUserLogger,
|
|
26
68
|
makeOnBlockArgs,
|
|
27
69
|
}
|
|
28
|
-
/*
|
|
70
|
+
/* Logging Not a pure module */
|
package/src/Env.res
CHANGED
|
@@ -8,8 +8,6 @@ let updateSyncTimeOnRestart =
|
|
|
8
8
|
envSafe->EnvSafe.get("UPDATE_SYNC_TIME_ON_RESTART", S.bool, ~fallback=true)
|
|
9
9
|
let targetBufferSize = envSafe->EnvSafe.get("ENVIO_INDEXING_MAX_BUFFER_SIZE", S.option(S.int))
|
|
10
10
|
let maxAddrInPartition = envSafe->EnvSafe.get("MAX_PARTITION_SIZE", S.int, ~fallback=5_000)
|
|
11
|
-
let maxPartitionConcurrency =
|
|
12
|
-
envSafe->EnvSafe.get("ENVIO_MAX_PARTITION_CONCURRENCY", S.int, ~fallback=10)
|
|
13
11
|
|
|
14
12
|
// Target number of in-memory objects (uncommitted entity/effect changes plus
|
|
15
13
|
// unwritten batch items) the store holds before processing waits for the write
|
package/src/Env.res.mjs
CHANGED
|
@@ -19,8 +19,6 @@ let targetBufferSize = EnvSafe.get(envSafe, "ENVIO_INDEXING_MAX_BUFFER_SIZE", S$
|
|
|
19
19
|
|
|
20
20
|
let maxAddrInPartition = EnvSafe.get(envSafe, "MAX_PARTITION_SIZE", S$RescriptSchema.int, undefined, 5000, undefined, undefined);
|
|
21
21
|
|
|
22
|
-
let maxPartitionConcurrency = EnvSafe.get(envSafe, "ENVIO_MAX_PARTITION_CONCURRENCY", S$RescriptSchema.int, undefined, 10, undefined, undefined);
|
|
23
|
-
|
|
24
22
|
let inMemoryObjectsTarget = EnvSafe.get(envSafe, "ENVIO_IN_MEMORY_OBJECTS_TARGET", S$RescriptSchema.int, undefined, 100000, undefined, undefined);
|
|
25
23
|
|
|
26
24
|
let serverPort = EnvSafe.get(envSafe, "ENVIO_INDEXER_PORT", S$RescriptSchema.port(S$RescriptSchema.int, undefined), undefined, EnvSafe.get(envSafe, "METRICS_PORT", S$RescriptSchema.port(S$RescriptSchema.int, undefined), undefined, 9898, undefined, undefined), undefined, undefined);
|
|
@@ -222,7 +220,6 @@ export {
|
|
|
222
220
|
updateSyncTimeOnRestart,
|
|
223
221
|
targetBufferSize,
|
|
224
222
|
maxAddrInPartition,
|
|
225
|
-
maxPartitionConcurrency,
|
|
226
223
|
inMemoryObjectsTarget,
|
|
227
224
|
serverPort,
|
|
228
225
|
tuiEnvVar,
|
|
@@ -312,7 +312,7 @@ let resolveFieldSelection = (
|
|
|
312
312
|
// ============== Client-side address filter ==============
|
|
313
313
|
|
|
314
314
|
let compileAddressFilter: string => (
|
|
315
|
-
Internal.
|
|
315
|
+
Internal.eventPayload,
|
|
316
316
|
int,
|
|
317
317
|
dict<Internal.indexingContract>,
|
|
318
318
|
) => bool = %raw(`function (body) {
|
|
@@ -339,7 +339,7 @@ let buildAddressFilterBody = (groups: array<array<string>>): option<string> => {
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
let buildAddressFilter = (groups: array<array<string>>): option<
|
|
342
|
-
(Internal.
|
|
342
|
+
(Internal.eventPayload, int, dict<Internal.indexingContract>) => bool,
|
|
343
343
|
> => buildAddressFilterBody(groups)->Option.map(compileAddressFilter)
|
|
344
344
|
|
|
345
345
|
// ============== Build complete EVM event config ==============
|
package/src/EventProcessing.res
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
let allChainsEventsProcessedToEndblock = (
|
|
2
|
-
|
|
3
|
-
->
|
|
4
|
-
->Array.every(
|
|
1
|
+
let allChainsEventsProcessedToEndblock = (chainStates: dict<ChainState.t>) => {
|
|
2
|
+
chainStates
|
|
3
|
+
->Dict.valuesToArray
|
|
4
|
+
->Array.every(cs => cs->ChainState.hasProcessedToEndblock)
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
let computeChainsState = (
|
|
7
|
+
let computeChainsState = (chainStates: dict<ChainState.t>): Internal.chains => {
|
|
8
8
|
let chains = Dict.make()
|
|
9
9
|
|
|
10
|
-
let
|
|
10
|
+
let values = chainStates->Dict.valuesToArray
|
|
11
|
+
let isRealtime = values->Array.every(cs => cs->ChainState.isReady)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
->Array.forEach(chain => {
|
|
15
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
13
|
+
values->Array.forEach(cs => {
|
|
14
|
+
let chainId = (cs->ChainState.chainConfig).id
|
|
16
15
|
chains->Dict.set(
|
|
17
16
|
chainId->Int.toString,
|
|
18
17
|
{
|
|
@@ -31,7 +30,7 @@ let runEventHandlerOrThrow = async (
|
|
|
31
30
|
item: Internal.item,
|
|
32
31
|
~checkpointId,
|
|
33
32
|
~handler,
|
|
34
|
-
~
|
|
33
|
+
~indexerState,
|
|
35
34
|
~loadManager,
|
|
36
35
|
~persistence,
|
|
37
36
|
~chains: Internal.chains,
|
|
@@ -46,7 +45,7 @@ let runEventHandlerOrThrow = async (
|
|
|
46
45
|
let contextParams: UserContext.contextParams = {
|
|
47
46
|
item,
|
|
48
47
|
checkpointId,
|
|
49
|
-
|
|
48
|
+
indexerState,
|
|
50
49
|
loadManager,
|
|
51
50
|
persistence,
|
|
52
51
|
isPreload: false,
|
|
@@ -57,7 +56,7 @@ let runEventHandlerOrThrow = async (
|
|
|
57
56
|
await handler(
|
|
58
57
|
(
|
|
59
58
|
{
|
|
60
|
-
event:
|
|
59
|
+
event: item->Ecosystem.getItemEvent(~ecosystem=config.ecosystem),
|
|
61
60
|
context: UserContext.getHandlerContext(contextParams),
|
|
62
61
|
}: Internal.handlerArgs
|
|
63
62
|
),
|
|
@@ -84,9 +83,10 @@ let runEventHandlerOrThrow = async (
|
|
|
84
83
|
let runHandlerOrThrow = async (
|
|
85
84
|
item: Internal.item,
|
|
86
85
|
~checkpointId,
|
|
87
|
-
~
|
|
86
|
+
~indexerState,
|
|
88
87
|
~loadManager,
|
|
89
|
-
~
|
|
88
|
+
~persistence: Persistence.t,
|
|
89
|
+
~config: Config.t,
|
|
90
90
|
~chains: Internal.chains,
|
|
91
91
|
) => {
|
|
92
92
|
switch item {
|
|
@@ -94,19 +94,19 @@ let runHandlerOrThrow = async (
|
|
|
94
94
|
try {
|
|
95
95
|
let contextParams: UserContext.contextParams = {
|
|
96
96
|
item,
|
|
97
|
-
|
|
97
|
+
indexerState,
|
|
98
98
|
loadManager,
|
|
99
|
-
persistence
|
|
99
|
+
persistence,
|
|
100
100
|
checkpointId,
|
|
101
101
|
isPreload: false,
|
|
102
102
|
chains,
|
|
103
|
-
config
|
|
103
|
+
config,
|
|
104
104
|
isResolved: false,
|
|
105
105
|
}
|
|
106
106
|
await handler(
|
|
107
107
|
Ecosystem.makeOnBlockArgs(
|
|
108
108
|
~blockNumber,
|
|
109
|
-
~ecosystem=
|
|
109
|
+
~ecosystem=config.ecosystem,
|
|
110
110
|
~context=UserContext.getHandlerContext(contextParams),
|
|
111
111
|
),
|
|
112
112
|
)
|
|
@@ -121,16 +121,17 @@ let runHandlerOrThrow = async (
|
|
|
121
121
|
}),
|
|
122
122
|
)
|
|
123
123
|
}
|
|
124
|
-
| Event({eventConfig}) =>
|
|
124
|
+
| Event({eventConfig}) =>
|
|
125
|
+
switch eventConfig.handler {
|
|
125
126
|
| Some(handler) =>
|
|
126
127
|
await item->runEventHandlerOrThrow(
|
|
127
128
|
~handler,
|
|
128
129
|
~checkpointId,
|
|
129
|
-
~
|
|
130
|
+
~indexerState,
|
|
130
131
|
~loadManager,
|
|
131
|
-
~persistence
|
|
132
|
+
~persistence,
|
|
132
133
|
~chains,
|
|
133
|
-
~config
|
|
134
|
+
~config,
|
|
134
135
|
)
|
|
135
136
|
| None => ()
|
|
136
137
|
}
|
|
@@ -142,7 +143,7 @@ let preloadBatchOrThrow = async (
|
|
|
142
143
|
~loadManager,
|
|
143
144
|
~persistence,
|
|
144
145
|
~config: Config.t,
|
|
145
|
-
~
|
|
146
|
+
~indexerState,
|
|
146
147
|
~chains: Internal.chains,
|
|
147
148
|
) => {
|
|
148
149
|
// On the first run of loaders, we don't care about the result,
|
|
@@ -160,7 +161,7 @@ let preloadBatchOrThrow = async (
|
|
|
160
161
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
161
162
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
162
163
|
switch item {
|
|
163
|
-
| Event({eventConfig: {handler, contractName, name: eventName}
|
|
164
|
+
| Event({eventConfig: {handler, contractName, name: eventName}}) =>
|
|
164
165
|
switch handler {
|
|
165
166
|
| None => ()
|
|
166
167
|
| Some(handler) =>
|
|
@@ -171,10 +172,10 @@ let preloadBatchOrThrow = async (
|
|
|
171
172
|
)
|
|
172
173
|
promises->Array.push(
|
|
173
174
|
handler({
|
|
174
|
-
event,
|
|
175
|
+
event: item->Ecosystem.getItemEvent(~ecosystem=config.ecosystem),
|
|
175
176
|
context: UserContext.getHandlerContext({
|
|
176
177
|
item,
|
|
177
|
-
|
|
178
|
+
indexerState,
|
|
178
179
|
loadManager,
|
|
179
180
|
persistence,
|
|
180
181
|
checkpointId,
|
|
@@ -208,7 +209,7 @@ let preloadBatchOrThrow = async (
|
|
|
208
209
|
~ecosystem=config.ecosystem,
|
|
209
210
|
~context=UserContext.getHandlerContext({
|
|
210
211
|
item,
|
|
211
|
-
|
|
212
|
+
indexerState,
|
|
212
213
|
loadManager,
|
|
213
214
|
persistence,
|
|
214
215
|
checkpointId,
|
|
@@ -234,9 +235,10 @@ let preloadBatchOrThrow = async (
|
|
|
234
235
|
|
|
235
236
|
let runBatchHandlersOrThrow = async (
|
|
236
237
|
batch: Batch.t,
|
|
237
|
-
~
|
|
238
|
+
~indexerState,
|
|
238
239
|
~loadManager,
|
|
239
|
-
~
|
|
240
|
+
~persistence,
|
|
241
|
+
~config,
|
|
240
242
|
~chains: Internal.chains,
|
|
241
243
|
) => {
|
|
242
244
|
let itemIdx = ref(0)
|
|
@@ -248,7 +250,15 @@ let runBatchHandlersOrThrow = async (
|
|
|
248
250
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
249
251
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
250
252
|
|
|
251
|
-
await runHandlerOrThrow(
|
|
253
|
+
await runHandlerOrThrow(
|
|
254
|
+
item,
|
|
255
|
+
~checkpointId,
|
|
256
|
+
~indexerState,
|
|
257
|
+
~loadManager,
|
|
258
|
+
~persistence,
|
|
259
|
+
~config,
|
|
260
|
+
~chains,
|
|
261
|
+
)
|
|
252
262
|
}
|
|
253
263
|
itemIdx := itemIdx.contents + checkpointEventsProcessed
|
|
254
264
|
}
|
|
@@ -273,14 +283,15 @@ type logPartitionInfo = {
|
|
|
273
283
|
|
|
274
284
|
let processEventBatch = async (
|
|
275
285
|
~batch: Batch.t,
|
|
276
|
-
~
|
|
286
|
+
~indexerState: IndexerState.t,
|
|
277
287
|
~loadManager,
|
|
278
|
-
~
|
|
279
|
-
~
|
|
288
|
+
~persistence: Persistence.t,
|
|
289
|
+
~config: Config.t,
|
|
290
|
+
~chainStates: dict<ChainState.t>,
|
|
280
291
|
) => {
|
|
281
292
|
let totalBatchSize = batch.totalBatchSize
|
|
282
293
|
// Compute chains state for this batch
|
|
283
|
-
let chains: Internal.chains =
|
|
294
|
+
let chains: Internal.chains = chainStates->computeChainsState
|
|
284
295
|
|
|
285
296
|
let logger = Logging.getLogger()
|
|
286
297
|
logger->Logging.childTrace({
|
|
@@ -296,29 +307,29 @@ let processEventBatch = async (
|
|
|
296
307
|
|
|
297
308
|
try {
|
|
298
309
|
// Backpressure: keep processing within keepLatestChangesLimit of the cycle.
|
|
299
|
-
await
|
|
310
|
+
await indexerState->Writing.awaitCapacity
|
|
300
311
|
|
|
301
312
|
let timeRef = Hrtime.makeTimer()
|
|
302
313
|
|
|
303
314
|
if batch.items->Utils.Array.notEmpty {
|
|
304
|
-
await batch->preloadBatchOrThrow(
|
|
305
|
-
~loadManager,
|
|
306
|
-
~persistence=ctx.persistence,
|
|
307
|
-
~inMemoryStore,
|
|
308
|
-
~chains,
|
|
309
|
-
~config=ctx.config,
|
|
310
|
-
)
|
|
315
|
+
await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
|
|
311
316
|
}
|
|
312
317
|
|
|
313
318
|
let elapsedTimeAfterLoaders = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
314
319
|
|
|
315
320
|
if batch.items->Utils.Array.notEmpty {
|
|
316
|
-
await batch->runBatchHandlersOrThrow(
|
|
321
|
+
await batch->runBatchHandlersOrThrow(
|
|
322
|
+
~indexerState,
|
|
323
|
+
~loadManager,
|
|
324
|
+
~persistence,
|
|
325
|
+
~config,
|
|
326
|
+
~chains,
|
|
327
|
+
)
|
|
317
328
|
}
|
|
318
329
|
|
|
319
330
|
let elapsedTimeAfterProcessing = timeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
320
331
|
|
|
321
|
-
|
|
332
|
+
indexerState->Writing.commitBatch(~batch)
|
|
322
333
|
|
|
323
334
|
let loaderDuration = elapsedTimeAfterLoaders
|
|
324
335
|
let handlerDuration = elapsedTimeAfterProcessing -. loaderDuration
|
|
@@ -329,7 +340,10 @@ let processEventBatch = async (
|
|
|
329
340
|
reason->ErrorHandling.make(~msg=message, ~logger)->Error
|
|
330
341
|
| ProcessingError({message, exn, item}) =>
|
|
331
342
|
exn
|
|
332
|
-
->ErrorHandling.make(
|
|
343
|
+
->ErrorHandling.make(
|
|
344
|
+
~msg=message,
|
|
345
|
+
~logger=Ecosystem.getItemLogger(item, ~ecosystem=config.ecosystem),
|
|
346
|
+
)
|
|
333
347
|
->Error
|
|
334
348
|
| exn => exn->ErrorHandling.make(~msg="Failed processing batch", ~logger)->Error
|
|
335
349
|
}
|