envio 3.11.0 → 3.12.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/index.d.ts +3 -0
- package/package.json +6 -6
- package/src/Batch.res +111 -78
- package/src/Batch.res.mjs +53 -46
- package/src/BatchProcessing.res +1 -11
- package/src/BatchProcessing.res.mjs +1 -4
- package/src/ChainFetching.res +7 -3
- package/src/ChainFetching.res.mjs +1 -1
- package/src/ChainState.res +82 -20
- package/src/ChainState.res.mjs +51 -13
- package/src/ChainState.resi +6 -1
- package/src/Config.res +58 -37
- package/src/Config.res.mjs +63 -53
- package/src/CrossChainState.res +50 -53
- package/src/CrossChainState.res.mjs +25 -23
- package/src/CrossChainState.resi +6 -13
- package/src/EffectState.res +13 -4
- package/src/EffectState.resi +7 -1
- package/src/EventProcessing.res +6 -6
- package/src/EventProcessing.res.mjs +6 -6
- package/src/FetchState.res +65 -46
- package/src/FetchState.res.mjs +68 -36
- package/src/FinalizeBackfill.res +16 -12
- package/src/FinalizeBackfill.res.mjs +3 -3
- package/src/HistoryPolicy.res +46 -0
- package/src/HistoryPolicy.res.mjs +50 -0
- package/src/InMemoryStore.res +30 -32
- package/src/InMemoryStore.res.mjs +33 -28
- package/src/InMemoryTable.res +155 -67
- package/src/InMemoryTable.res.mjs +151 -60
- package/src/IndexerState.res +66 -45
- package/src/IndexerState.res.mjs +57 -29
- package/src/IndexerState.resi +8 -13
- package/src/Internal.res +4 -2
- package/src/LoadLayer.res +68 -38
- package/src/LoadLayer.res.mjs +50 -64
- package/src/LoadLayer.resi +1 -1
- package/src/Main.res +25 -24
- package/src/Main.res.mjs +24 -25
- package/src/Metrics.res +49 -1
- package/src/Metrics.res.mjs +26 -3
- package/src/Persistence.res +55 -16
- package/src/Persistence.res.mjs +18 -3
- package/src/PgStorage.res +286 -180
- package/src/PgStorage.res.mjs +209 -122
- package/src/PruneStaleHistory.res +9 -15
- package/src/PruneStaleHistory.res.mjs +11 -20
- package/src/Rollback.res +9 -14
- package/src/Rollback.res.mjs +5 -3
- package/src/Sink.res +7 -5
- package/src/Sink.res.mjs +4 -4
- package/src/Staging.res +298 -0
- package/src/Staging.res.mjs +257 -0
- package/src/TestIndexer.res +14 -30
- package/src/TestIndexer.res.mjs +11 -9
- package/src/UserContext.res +20 -36
- package/src/UserContext.res.mjs +6 -9
- package/src/Utils.res +10 -4
- package/src/Utils.res.mjs +16 -16
- package/src/Writing.res +34 -20
- package/src/Writing.res.mjs +15 -20
- package/src/bindings/ClickHouse.res +41 -34
- package/src/bindings/ClickHouse.res.mjs +36 -30
- package/src/bindings/ClickHouseSink.res +45 -186
- package/src/bindings/ClickHouseSink.res.mjs +21 -174
- package/src/db/CheckpointSequence.res +109 -0
- package/src/db/CheckpointSequence.res.mjs +99 -0
- package/src/db/EntityFilter.res +487 -275
- package/src/db/EntityFilter.res.mjs +557 -309
- package/src/db/EntityHistory.res +6 -5
- package/src/db/EntityHistory.res.mjs +5 -5
- package/src/db/Frontier.res +86 -0
- package/src/db/Frontier.res.mjs +126 -0
- package/src/db/InternalTable.res +145 -27
- package/src/db/InternalTable.res.mjs +115 -29
- package/src/db/RollbackFloors.res +34 -41
- package/src/db/RollbackFloors.res.mjs +27 -71
- package/src/db/Table.res +21 -6
- package/src/db/Table.res.mjs +13 -4
- package/src/sources/BlockStore.res +8 -0
- package/src/sources/EvmHyperSyncSource.res +5 -1
- package/src/sources/EvmHyperSyncSource.res.mjs +4 -3
- package/src/sources/FuelHyperSyncSource.res +1 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +1 -1
- package/src/sources/HyperSync.res +6 -0
- package/src/sources/HyperSync.res.mjs +5 -2
- package/src/sources/HyperSync.resi +2 -0
- package/src/sources/HyperSyncClient.res +6 -0
- package/src/sources/HyperSyncSSE.res +1 -1
- package/src/sources/HyperSyncSSE.res.mjs +4 -10
- package/src/sources/RequestStat.res +8 -1
- package/src/sources/RpcSource.res +1 -0
- package/src/sources/RpcSource.res.mjs +1 -1
- package/src/sources/SimulateSource.res +1 -0
- package/src/sources/SimulateSource.res.mjs +1 -1
- package/src/sources/Source.res +11 -3
- package/src/sources/SourceManager.res +34 -13
- package/src/sources/SourceManager.res.mjs +26 -9
- package/src/sources/SourceManager.resi +2 -0
- package/src/sources/SvmHyperSyncClient.res +5 -0
- package/src/sources/SvmHyperSyncSource.res +3 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +4 -2
- package/src/tui/Tui.res +56 -143
- package/src/tui/Tui.res.mjs +70 -166
- package/src/tui/components/TuiData.res +61 -16
- package/src/tui/components/TuiData.res.mjs +53 -15
- package/svm.schema.json +0 -7
- package/src/db/CheckpointBounds.res +0 -53
- package/src/db/CheckpointBounds.res.mjs +0 -44
package/index.d.ts
CHANGED
|
@@ -1216,6 +1216,9 @@ export type SvmAllTransactionFields = {
|
|
|
1216
1216
|
readonly err: string | undefined;
|
|
1217
1217
|
readonly fee: bigint;
|
|
1218
1218
|
readonly computeUnitsConsumed: bigint | undefined;
|
|
1219
|
+
/** Every account the transaction resolves to: the static keys, then the
|
|
1220
|
+
* address lookup tables' writable then readonly addresses. A transaction's
|
|
1221
|
+
* account indexes address this list. */
|
|
1219
1222
|
readonly accountKeys: readonly string[];
|
|
1220
1223
|
readonly recentBlockhash: string;
|
|
1221
1224
|
readonly version: string | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -68,10 +68,10 @@
|
|
|
68
68
|
"tsx": "4.21.0"
|
|
69
69
|
},
|
|
70
70
|
"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.
|
|
71
|
+
"envio-linux-x64": "3.12.1",
|
|
72
|
+
"envio-linux-x64-musl": "3.12.1",
|
|
73
|
+
"envio-linux-arm64": "3.12.1",
|
|
74
|
+
"envio-darwin-x64": "3.12.1",
|
|
75
|
+
"envio-darwin-arm64": "3.12.1"
|
|
76
76
|
}
|
|
77
77
|
}
|
package/src/Batch.res
CHANGED
|
@@ -4,6 +4,12 @@ open Utils.UnsafeIntOperators
|
|
|
4
4
|
type chainAfterBatch = {
|
|
5
5
|
batchSize: int,
|
|
6
6
|
progressBlockNumber: int,
|
|
7
|
+
// Timestamp of `progressBlockNumber` itself, never of a lower block, so it
|
|
8
|
+
// measures how far behind chain time the committed progress is. `None` when
|
|
9
|
+
// the source didn't return that block's header - during backfill it only
|
|
10
|
+
// returns blocks carrying items, and an SVM slot may have produced no block
|
|
11
|
+
// at all.
|
|
12
|
+
progressBlockTime: option<int>,
|
|
7
13
|
sourceBlockNumber: int,
|
|
8
14
|
totalEventsProcessed: float,
|
|
9
15
|
fetchState: FetchState.t,
|
|
@@ -23,6 +29,10 @@ type reorgHashSnapshot = {
|
|
|
23
29
|
type chainBeforeBatch = {
|
|
24
30
|
fetchState: FetchState.t,
|
|
25
31
|
scannedHashes: reorgHashSnapshot,
|
|
32
|
+
// The progress block isn't known until the build computes it, so its
|
|
33
|
+
// timestamp can't be snapshotted with the rest. Reads the chain's store,
|
|
34
|
+
// which the synchronous build can't see mutate.
|
|
35
|
+
blockTimeAt: int => option<int>,
|
|
26
36
|
shouldRollbackOnReorg: bool,
|
|
27
37
|
progressBlockNumber: int,
|
|
28
38
|
sourceBlockNumber: int,
|
|
@@ -34,24 +44,32 @@ type t = {
|
|
|
34
44
|
totalBatchSize: int,
|
|
35
45
|
items: array<Internal.item>,
|
|
36
46
|
progressedChainsById: dict<chainAfterBatch>,
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
47
|
+
// Whether the batch's rows get history. Writes never merge across a change in
|
|
48
|
+
// it, so a single write can't mix the two.
|
|
49
|
+
history: HistoryPolicy.t,
|
|
40
50
|
// Unnest-like checkpoint fields:
|
|
41
51
|
checkpointIds: array<bigint>,
|
|
42
52
|
checkpointChainIds: array<ChainId.t>,
|
|
43
53
|
checkpointBlockNumbers: array<int>,
|
|
44
54
|
checkpointBlockHashes: array<Null.t<string>>,
|
|
55
|
+
// Items the checkpoint carries, which is what indexes `items`.
|
|
56
|
+
checkpointItemsCount: array<int>,
|
|
57
|
+
// Logs the checkpoint carries: one log routed to several registrations is one
|
|
58
|
+
// event, however many items it made.
|
|
45
59
|
checkpointEventsProcessed: array<int>,
|
|
46
60
|
registeredAddresses: array<AddressRows.staged>,
|
|
47
61
|
}
|
|
48
62
|
|
|
63
|
+
// What a chain contributed to the batch: items taken off its buffer, and the
|
|
64
|
+
// logs behind them.
|
|
65
|
+
type chainBatchCounts = {size: int, eventsProcessed: int}
|
|
66
|
+
|
|
49
67
|
let getProgressedChainsById = {
|
|
50
68
|
let getChainAfterBatchIfProgressed = (
|
|
51
69
|
~chainBeforeBatch: chainBeforeBatch,
|
|
52
70
|
~progressBlockNumberAfterBatch,
|
|
53
71
|
~fetchStateAfterBatch,
|
|
54
|
-
~
|
|
72
|
+
~counts: chainBatchCounts,
|
|
55
73
|
) => {
|
|
56
74
|
// The check is sufficient, since we guarantee to include a full block in a batch
|
|
57
75
|
// Also, this might be true even if batchSize is 0,
|
|
@@ -60,10 +78,12 @@ let getProgressedChainsById = {
|
|
|
60
78
|
Some(
|
|
61
79
|
(
|
|
62
80
|
{
|
|
63
|
-
batchSize,
|
|
81
|
+
batchSize: counts.size,
|
|
64
82
|
progressBlockNumber: progressBlockNumberAfterBatch,
|
|
83
|
+
progressBlockTime: chainBeforeBatch.blockTimeAt(progressBlockNumberAfterBatch),
|
|
65
84
|
sourceBlockNumber: chainBeforeBatch.sourceBlockNumber,
|
|
66
|
-
totalEventsProcessed: chainBeforeBatch.totalEventsProcessed +.
|
|
85
|
+
totalEventsProcessed: chainBeforeBatch.totalEventsProcessed +.
|
|
86
|
+
counts.eventsProcessed->Int.toFloat,
|
|
67
87
|
fetchState: fetchStateAfterBatch,
|
|
68
88
|
isProgressAtHeadWhenBatchCreated: progressBlockNumberAfterBatch >=
|
|
69
89
|
chainBeforeBatch.sourceBlockNumber - chainBeforeBatch.chainConfig.blockLag,
|
|
@@ -77,7 +97,7 @@ let getProgressedChainsById = {
|
|
|
77
97
|
|
|
78
98
|
(
|
|
79
99
|
~chainsBeforeBatch: dict<chainBeforeBatch>,
|
|
80
|
-
~
|
|
100
|
+
~countsPerChain: dict<chainBatchCounts>,
|
|
81
101
|
~progressBlockNumberPerChain: dict<int>,
|
|
82
102
|
) => {
|
|
83
103
|
let progressedChainsById = Dict.make()
|
|
@@ -98,14 +118,14 @@ let getProgressedChainsById = {
|
|
|
98
118
|
| None => chainBeforeBatch.progressBlockNumber
|
|
99
119
|
}
|
|
100
120
|
|
|
101
|
-
switch switch
|
|
121
|
+
switch switch countsPerChain->Utils.Dict.dangerouslyGetNonOption(
|
|
102
122
|
fetchState.chainId->ChainId.toString,
|
|
103
123
|
) {
|
|
104
|
-
| Some(
|
|
105
|
-
let leftItems = fetchState.buffer->Array.slice(~start=
|
|
124
|
+
| Some(counts) =>
|
|
125
|
+
let leftItems = fetchState.buffer->Array.slice(~start=counts.size)
|
|
106
126
|
getChainAfterBatchIfProgressed(
|
|
107
127
|
~chainBeforeBatch,
|
|
108
|
-
~
|
|
128
|
+
~counts,
|
|
109
129
|
~fetchStateAfterBatch=fetchState->FetchState.updateInternal(~mutItems=leftItems),
|
|
110
130
|
~progressBlockNumberAfterBatch,
|
|
111
131
|
)
|
|
@@ -113,7 +133,7 @@ let getProgressedChainsById = {
|
|
|
113
133
|
| None =>
|
|
114
134
|
getChainAfterBatchIfProgressed(
|
|
115
135
|
~chainBeforeBatch,
|
|
116
|
-
~
|
|
136
|
+
~counts={size: 0, eventsProcessed: 0},
|
|
117
137
|
~fetchStateAfterBatch=chainBeforeBatch.fetchState,
|
|
118
138
|
~progressBlockNumberAfterBatch,
|
|
119
139
|
)
|
|
@@ -146,7 +166,7 @@ let seekFirstAbove = (blockNumbers: array<int>, blockNumber) => {
|
|
|
146
166
|
|
|
147
167
|
@inline
|
|
148
168
|
let addReorgCheckpoints = (
|
|
149
|
-
~
|
|
169
|
+
~cursor,
|
|
150
170
|
~scannedHashes: reorgHashSnapshot,
|
|
151
171
|
~shouldRollbackOnReorg,
|
|
152
172
|
~fromBlockExclusive,
|
|
@@ -156,10 +176,10 @@ let addReorgCheckpoints = (
|
|
|
156
176
|
~mutCheckpointChainIds,
|
|
157
177
|
~mutCheckpointBlockNumbers,
|
|
158
178
|
~mutCheckpointBlockHashes,
|
|
179
|
+
~mutCheckpointItemsCount,
|
|
159
180
|
~mutCheckpointEventsProcessed,
|
|
160
181
|
) => {
|
|
161
182
|
if shouldRollbackOnReorg {
|
|
162
|
-
let prevCheckpointId = ref(prevCheckpointId)
|
|
163
183
|
// The snapshot already holds only in-threshold scanned hashes, ascending,
|
|
164
184
|
// so seeking to the gap's lower bound gives the gap checkpoints without
|
|
165
185
|
// rescanning the whole snapshot for every gap in the batch.
|
|
@@ -172,37 +192,30 @@ let addReorgCheckpoints = (
|
|
|
172
192
|
scannedHashes.hashByBlockNumber
|
|
173
193
|
->Utils.Dict.dangerouslyGetByIntNonOption(blockNumber)
|
|
174
194
|
->Option.getUnsafe
|
|
175
|
-
let checkpointId =
|
|
176
|
-
prevCheckpointId := checkpointId
|
|
195
|
+
let checkpointId = cursor->CheckpointSequence.next(~chainId)
|
|
177
196
|
|
|
178
197
|
mutCheckpointIds->Array.push(checkpointId)
|
|
179
198
|
mutCheckpointChainIds->Array.push(chainId)
|
|
180
199
|
mutCheckpointBlockNumbers->Array.push(blockNumber)
|
|
181
200
|
mutCheckpointBlockHashes->Array.push(Null.Value(hash))
|
|
201
|
+
mutCheckpointItemsCount->Array.push(0)
|
|
182
202
|
mutCheckpointEventsProcessed->Array.push(0)
|
|
183
203
|
|
|
184
204
|
idx := idx.contents + 1
|
|
185
205
|
}
|
|
186
|
-
prevCheckpointId.contents
|
|
187
|
-
} else {
|
|
188
|
-
prevCheckpointId
|
|
189
206
|
}
|
|
190
207
|
}
|
|
191
208
|
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
// interleave freely *across* chains, which is exactly why that predicate can't
|
|
200
|
-
// be the id bound alone.
|
|
201
|
-
let prepareBatch = (
|
|
202
|
-
~checkpointIdBeforeBatch,
|
|
209
|
+
// Within a chain, ids ascend with block order, and rollback preserves that by
|
|
210
|
+
// deleting the chain's ids above its target before any higher one is allocated.
|
|
211
|
+
// Every rollback deletes by `id > target`, which is only the stale suffix while
|
|
212
|
+
// ids and blocks agree on order within each chain.
|
|
213
|
+
let make = (
|
|
214
|
+
~sequence: CheckpointSequence.t,
|
|
215
|
+
~frontier: Frontier.t,
|
|
203
216
|
~chainsBeforeBatch: dict<chainBeforeBatch>,
|
|
204
217
|
~batchSizeTarget,
|
|
205
|
-
~
|
|
218
|
+
~history,
|
|
206
219
|
) => {
|
|
207
220
|
let preparedFetchStates =
|
|
208
221
|
chainsBeforeBatch
|
|
@@ -214,8 +227,8 @@ let prepareBatch = (
|
|
|
214
227
|
let preparedNumber = preparedFetchStates->Array.length
|
|
215
228
|
let totalBatchSize = ref(0)
|
|
216
229
|
|
|
217
|
-
let
|
|
218
|
-
let
|
|
230
|
+
let cursor = sequence->CheckpointSequence.cursor(~frontier)
|
|
231
|
+
let mutCountsPerChain = Dict.make()
|
|
219
232
|
let mutProgressBlockNumberPerChain = Dict.make()
|
|
220
233
|
|
|
221
234
|
let items = []
|
|
@@ -223,6 +236,7 @@ let prepareBatch = (
|
|
|
223
236
|
let checkpointChainIds = []
|
|
224
237
|
let checkpointBlockNumbers = []
|
|
225
238
|
let checkpointBlockHashes = []
|
|
239
|
+
let checkpointItemsCount = []
|
|
226
240
|
let checkpointEventsProcessed = []
|
|
227
241
|
|
|
228
242
|
// Accumulate items for all actively indexing chains
|
|
@@ -241,29 +255,38 @@ let prepareBatch = (
|
|
|
241
255
|
->Option.getUnsafe
|
|
242
256
|
|
|
243
257
|
let prevBlockNumber = ref(chainBeforeBatch.progressBlockNumber)
|
|
258
|
+
let chainEventsProcessed = ref(0)
|
|
244
259
|
if chainBatchSize > 0 {
|
|
245
260
|
for idx in 0 to chainBatchSize - 1 {
|
|
246
261
|
let item = fetchState.buffer->Array.getUnsafe(idx)
|
|
247
262
|
let blockNumber = item->Internal.getItemBlockNumber
|
|
263
|
+
// The buffer is sorted, so a log's items are consecutive: the first of
|
|
264
|
+
// them is the only one that counts as an event.
|
|
265
|
+
let isNewEvent =
|
|
266
|
+
idx === 0 ||
|
|
267
|
+
!(fetchState.buffer->Array.getUnsafe(idx - 1)->FetchState.isSameLog(item))
|
|
268
|
+
if isNewEvent {
|
|
269
|
+
chainEventsProcessed := chainEventsProcessed.contents + 1
|
|
270
|
+
}
|
|
248
271
|
|
|
249
272
|
// Every new block we should create a new checkpoint
|
|
250
273
|
if blockNumber !== prevBlockNumber.contents {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
let checkpointId =
|
|
274
|
+
addReorgCheckpoints(
|
|
275
|
+
~chainId=fetchState.chainId,
|
|
276
|
+
~scannedHashes=chainBeforeBatch.scannedHashes,
|
|
277
|
+
~shouldRollbackOnReorg=chainBeforeBatch.shouldRollbackOnReorg,
|
|
278
|
+
~cursor,
|
|
279
|
+
~fromBlockExclusive=prevBlockNumber.contents,
|
|
280
|
+
~toBlockExclusive=blockNumber,
|
|
281
|
+
~mutCheckpointIds=checkpointIds,
|
|
282
|
+
~mutCheckpointChainIds=checkpointChainIds,
|
|
283
|
+
~mutCheckpointBlockNumbers=checkpointBlockNumbers,
|
|
284
|
+
~mutCheckpointBlockHashes=checkpointBlockHashes,
|
|
285
|
+
~mutCheckpointItemsCount=checkpointItemsCount,
|
|
286
|
+
~mutCheckpointEventsProcessed=checkpointEventsProcessed,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
let checkpointId = cursor->CheckpointSequence.next(~chainId=fetchState.chainId)
|
|
267
290
|
|
|
268
291
|
checkpointIds->Array.push(checkpointId)->ignore
|
|
269
292
|
checkpointChainIds->Array.push(fetchState.chainId)->ignore
|
|
@@ -278,41 +301,49 @@ let prepareBatch = (
|
|
|
278
301
|
},
|
|
279
302
|
)
|
|
280
303
|
->ignore
|
|
304
|
+
checkpointItemsCount->Array.push(1)->ignore
|
|
281
305
|
checkpointEventsProcessed->Array.push(1)->ignore
|
|
282
306
|
|
|
283
307
|
prevBlockNumber := blockNumber
|
|
284
|
-
prevCheckpointId := checkpointId
|
|
285
308
|
} else {
|
|
286
|
-
let lastIndex =
|
|
287
|
-
|
|
288
|
-
->Array.setUnsafe(lastIndex,
|
|
309
|
+
let lastIndex = checkpointItemsCount->Array.length - 1
|
|
310
|
+
checkpointItemsCount
|
|
311
|
+
->Array.setUnsafe(lastIndex, checkpointItemsCount->Array.getUnsafe(lastIndex) + 1)
|
|
289
312
|
->ignore
|
|
313
|
+
if isNewEvent {
|
|
314
|
+
checkpointEventsProcessed
|
|
315
|
+
->Array.setUnsafe(lastIndex, checkpointEventsProcessed->Array.getUnsafe(lastIndex) + 1)
|
|
316
|
+
->ignore
|
|
317
|
+
}
|
|
290
318
|
}
|
|
291
319
|
|
|
292
320
|
items->Array.push(item)->ignore
|
|
293
321
|
}
|
|
294
322
|
|
|
295
323
|
totalBatchSize := totalBatchSize.contents + chainBatchSize
|
|
296
|
-
|
|
324
|
+
mutCountsPerChain->ChainId.Dict.set(
|
|
325
|
+
fetchState.chainId,
|
|
326
|
+
{size: chainBatchSize, eventsProcessed: chainEventsProcessed.contents},
|
|
327
|
+
)
|
|
297
328
|
}
|
|
298
329
|
|
|
299
330
|
let progressBlockNumberAfterBatch =
|
|
300
331
|
fetchState->FetchState.getProgressBlockNumberAt(~index=chainBatchSize)
|
|
301
332
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
333
|
+
addReorgCheckpoints(
|
|
334
|
+
~chainId=fetchState.chainId,
|
|
335
|
+
~scannedHashes=chainBeforeBatch.scannedHashes,
|
|
336
|
+
~shouldRollbackOnReorg=chainBeforeBatch.shouldRollbackOnReorg,
|
|
337
|
+
~cursor,
|
|
338
|
+
~fromBlockExclusive=prevBlockNumber.contents,
|
|
339
|
+
~toBlockExclusive=progressBlockNumberAfterBatch + 1, // Make it inclusive
|
|
340
|
+
~mutCheckpointIds=checkpointIds,
|
|
341
|
+
~mutCheckpointChainIds=checkpointChainIds,
|
|
342
|
+
~mutCheckpointBlockNumbers=checkpointBlockNumbers,
|
|
343
|
+
~mutCheckpointBlockHashes=checkpointBlockHashes,
|
|
344
|
+
~mutCheckpointItemsCount=checkpointItemsCount,
|
|
345
|
+
~mutCheckpointEventsProcessed=checkpointEventsProcessed,
|
|
346
|
+
)
|
|
316
347
|
|
|
317
348
|
mutProgressBlockNumberPerChain->ChainId.Dict.set(
|
|
318
349
|
fetchState.chainId,
|
|
@@ -327,26 +358,28 @@ let prepareBatch = (
|
|
|
327
358
|
items,
|
|
328
359
|
progressedChainsById: getProgressedChainsById(
|
|
329
360
|
~chainsBeforeBatch,
|
|
330
|
-
~
|
|
361
|
+
~countsPerChain=mutCountsPerChain,
|
|
331
362
|
~progressBlockNumberPerChain=mutProgressBlockNumberPerChain,
|
|
332
363
|
),
|
|
333
|
-
|
|
364
|
+
history,
|
|
334
365
|
checkpointIds,
|
|
335
366
|
checkpointChainIds,
|
|
336
367
|
checkpointBlockNumbers,
|
|
337
368
|
checkpointBlockHashes,
|
|
369
|
+
checkpointItemsCount,
|
|
338
370
|
checkpointEventsProcessed,
|
|
339
371
|
registeredAddresses: [],
|
|
340
372
|
}
|
|
341
373
|
}
|
|
342
374
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
)
|
|
349
|
-
|
|
375
|
+
// Where the batch leaves each chain it handed ids to. Ids ascend within a
|
|
376
|
+
// chain, so the last one seen per chain is its highest.
|
|
377
|
+
let checkpointFrontier = (batch: t): Frontier.t => {
|
|
378
|
+
let frontier = Frontier.empty()
|
|
379
|
+
batch.checkpointChainIds->Array.forEachWithIndex((chainId, index) =>
|
|
380
|
+
frontier->Frontier.set(chainId, batch.checkpointIds->Array.getUnsafe(index))
|
|
381
|
+
)
|
|
382
|
+
frontier
|
|
350
383
|
}
|
|
351
384
|
|
|
352
385
|
let findFirstEventBlockNumber = (batch: t, ~chainId) => {
|
|
@@ -357,7 +390,7 @@ let findFirstEventBlockNumber = (batch: t, ~chainId) => {
|
|
|
357
390
|
let checkpointChainId = batch.checkpointChainIds->Array.getUnsafe(idx.contents)
|
|
358
391
|
if (
|
|
359
392
|
checkpointChainId === chainId &&
|
|
360
|
-
batch.
|
|
393
|
+
batch.checkpointItemsCount->Array.getUnsafe(idx.contents) > 0
|
|
361
394
|
) {
|
|
362
395
|
result := Some(batch.checkpointBlockNumbers->Array.getUnsafe(idx.contents))
|
|
363
396
|
} else {
|
package/src/Batch.res.mjs
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as ChainId from "./ChainId.res.mjs";
|
|
4
|
+
import * as Frontier from "./db/Frontier.res.mjs";
|
|
4
5
|
import * as FetchState from "./FetchState.res.mjs";
|
|
6
|
+
import * as CheckpointSequence from "./db/CheckpointSequence.res.mjs";
|
|
5
7
|
|
|
6
|
-
function getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, fetchStateAfterBatch,
|
|
8
|
+
function getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, fetchStateAfterBatch, counts) {
|
|
7
9
|
if (chainBeforeBatch.progressBlockNumber < progressBlockNumberAfterBatch) {
|
|
8
10
|
return {
|
|
9
|
-
batchSize:
|
|
11
|
+
batchSize: counts.size,
|
|
10
12
|
progressBlockNumber: progressBlockNumberAfterBatch,
|
|
13
|
+
progressBlockTime: chainBeforeBatch.blockTimeAt(progressBlockNumberAfterBatch),
|
|
11
14
|
sourceBlockNumber: chainBeforeBatch.sourceBlockNumber,
|
|
12
|
-
totalEventsProcessed: chainBeforeBatch.totalEventsProcessed +
|
|
15
|
+
totalEventsProcessed: chainBeforeBatch.totalEventsProcessed + counts.eventsProcessed,
|
|
13
16
|
fetchState: fetchStateAfterBatch,
|
|
14
17
|
isProgressAtHeadWhenBatchCreated: progressBlockNumberAfterBatch >= chainBeforeBatch.sourceBlockNumber - chainBeforeBatch.chainConfig.blockLag
|
|
15
18
|
};
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
function getProgressedChainsById(chainsBeforeBatch,
|
|
22
|
+
function getProgressedChainsById(chainsBeforeBatch, countsPerChain, progressBlockNumberPerChain) {
|
|
20
23
|
let progressedChainsById = {};
|
|
21
24
|
Object.values(chainsBeforeBatch).forEach(chainBeforeBatch => {
|
|
22
25
|
let fetchState = chainBeforeBatch.fetchState;
|
|
23
26
|
let progressBlockNumber = progressBlockNumberPerChain[ChainId.toString(fetchState.chainId)];
|
|
24
27
|
let progressBlockNumberAfterBatch = progressBlockNumber !== undefined ? progressBlockNumber : chainBeforeBatch.progressBlockNumber;
|
|
25
|
-
let
|
|
28
|
+
let counts = countsPerChain[ChainId.toString(fetchState.chainId)];
|
|
26
29
|
let progressedChain;
|
|
27
|
-
if (
|
|
28
|
-
let leftItems = fetchState.buffer.slice(
|
|
29
|
-
progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, FetchState.updateInternal(fetchState, undefined, leftItems, undefined, undefined, undefined),
|
|
30
|
+
if (counts !== undefined) {
|
|
31
|
+
let leftItems = fetchState.buffer.slice(counts.size);
|
|
32
|
+
progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, FetchState.updateInternal(fetchState, undefined, leftItems, undefined, undefined, undefined), counts);
|
|
30
33
|
} else {
|
|
31
|
-
progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, chainBeforeBatch.fetchState,
|
|
34
|
+
progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, chainBeforeBatch.fetchState, {
|
|
35
|
+
size: 0,
|
|
36
|
+
eventsProcessed: 0
|
|
37
|
+
});
|
|
32
38
|
}
|
|
33
39
|
if (progressedChain !== undefined) {
|
|
34
40
|
progressedChainsById[chainBeforeBatch.fetchState.chainId] = progressedChain;
|
|
@@ -52,145 +58,146 @@ function seekFirstAbove(blockNumbers, blockNumber) {
|
|
|
52
58
|
return low;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
function addReorgCheckpoints(
|
|
61
|
+
function addReorgCheckpoints(cursor, scannedHashes, shouldRollbackOnReorg, fromBlockExclusive, toBlockExclusive, chainId, mutCheckpointIds, mutCheckpointChainIds, mutCheckpointBlockNumbers, mutCheckpointBlockHashes, mutCheckpointItemsCount, mutCheckpointEventsProcessed) {
|
|
56
62
|
if (!shouldRollbackOnReorg) {
|
|
57
|
-
return
|
|
63
|
+
return;
|
|
58
64
|
}
|
|
59
|
-
let prevCheckpointId$1 = prevCheckpointId;
|
|
60
65
|
let blockNumbers = scannedHashes.blockNumbers;
|
|
61
66
|
let length = blockNumbers.length;
|
|
62
67
|
let idx = seekFirstAbove(blockNumbers, fromBlockExclusive);
|
|
63
68
|
while (idx < length && blockNumbers[idx] < toBlockExclusive) {
|
|
64
69
|
let blockNumber = blockNumbers[idx];
|
|
65
70
|
let hash = scannedHashes.hashByBlockNumber[blockNumber];
|
|
66
|
-
let checkpointId =
|
|
67
|
-
prevCheckpointId$1 = checkpointId;
|
|
71
|
+
let checkpointId = CheckpointSequence.next(cursor, chainId);
|
|
68
72
|
mutCheckpointIds.push(checkpointId);
|
|
69
73
|
mutCheckpointChainIds.push(chainId);
|
|
70
74
|
mutCheckpointBlockNumbers.push(blockNumber);
|
|
71
75
|
mutCheckpointBlockHashes.push(hash);
|
|
76
|
+
mutCheckpointItemsCount.push(0);
|
|
72
77
|
mutCheckpointEventsProcessed.push(0);
|
|
73
78
|
idx = idx + 1;
|
|
74
79
|
};
|
|
75
|
-
return prevCheckpointId$1;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
function
|
|
82
|
+
function make(sequence, frontier, chainsBeforeBatch, batchSizeTarget, history) {
|
|
79
83
|
let preparedFetchStates = FetchState.sortForBatch(Object.values(chainsBeforeBatch).map(chainBeforeBatch => chainBeforeBatch.fetchState), batchSizeTarget);
|
|
80
84
|
let chainIdx = 0;
|
|
81
85
|
let preparedNumber = preparedFetchStates.length;
|
|
82
86
|
let totalBatchSize = 0;
|
|
83
|
-
let
|
|
84
|
-
let
|
|
87
|
+
let cursor = CheckpointSequence.cursor(sequence, frontier);
|
|
88
|
+
let mutCountsPerChain = {};
|
|
85
89
|
let mutProgressBlockNumberPerChain = {};
|
|
86
90
|
let items = [];
|
|
87
91
|
let checkpointIds = [];
|
|
88
92
|
let checkpointChainIds = [];
|
|
89
93
|
let checkpointBlockNumbers = [];
|
|
90
94
|
let checkpointBlockHashes = [];
|
|
95
|
+
let checkpointItemsCount = [];
|
|
91
96
|
let checkpointEventsProcessed = [];
|
|
92
97
|
while (totalBatchSize < batchSizeTarget && chainIdx < preparedNumber) {
|
|
93
98
|
let fetchState = preparedFetchStates[chainIdx];
|
|
94
99
|
let chainBatchSize = FetchState.getReadyItemsCount(fetchState, batchSizeTarget - totalBatchSize, 0);
|
|
95
100
|
let chainBeforeBatch = chainsBeforeBatch[fetchState.chainId];
|
|
96
101
|
let prevBlockNumber = chainBeforeBatch.progressBlockNumber;
|
|
102
|
+
let chainEventsProcessed = 0;
|
|
97
103
|
if (chainBatchSize > 0) {
|
|
98
104
|
for (let idx = 0, idx_finish = chainBatchSize - 1; idx <= idx_finish; ++idx) {
|
|
99
105
|
let item = fetchState.buffer[idx];
|
|
100
106
|
let blockNumber = item.blockNumber;
|
|
107
|
+
let isNewEvent = idx === 0 || !FetchState.isSameLog(fetchState.buffer[idx - 1], item);
|
|
108
|
+
if (isNewEvent) {
|
|
109
|
+
chainEventsProcessed = chainEventsProcessed + 1;
|
|
110
|
+
}
|
|
101
111
|
if (blockNumber !== prevBlockNumber) {
|
|
102
112
|
let chainId = fetchState.chainId;
|
|
103
113
|
let fromBlockExclusive = prevBlockNumber;
|
|
104
114
|
let scannedHashes = chainBeforeBatch.scannedHashes;
|
|
105
|
-
let prevCheckpointId$1 = prevCheckpointId;
|
|
106
|
-
let tmp;
|
|
107
115
|
if (chainBeforeBatch.shouldRollbackOnReorg) {
|
|
108
|
-
let prevCheckpointId$2 = prevCheckpointId$1;
|
|
109
116
|
let blockNumbers = scannedHashes.blockNumbers;
|
|
110
117
|
let length = blockNumbers.length;
|
|
111
118
|
let idx$1 = seekFirstAbove(blockNumbers, fromBlockExclusive);
|
|
112
119
|
while (idx$1 < length && blockNumbers[idx$1] < blockNumber) {
|
|
113
120
|
let blockNumber$1 = blockNumbers[idx$1];
|
|
114
121
|
let hash = scannedHashes.hashByBlockNumber[blockNumber$1];
|
|
115
|
-
let checkpointId =
|
|
116
|
-
prevCheckpointId$2 = checkpointId;
|
|
122
|
+
let checkpointId = CheckpointSequence.next(cursor, chainId);
|
|
117
123
|
checkpointIds.push(checkpointId);
|
|
118
124
|
checkpointChainIds.push(chainId);
|
|
119
125
|
checkpointBlockNumbers.push(blockNumber$1);
|
|
120
126
|
checkpointBlockHashes.push(hash);
|
|
127
|
+
checkpointItemsCount.push(0);
|
|
121
128
|
checkpointEventsProcessed.push(0);
|
|
122
129
|
idx$1 = idx$1 + 1;
|
|
123
130
|
};
|
|
124
|
-
tmp = prevCheckpointId$2;
|
|
125
|
-
} else {
|
|
126
|
-
tmp = prevCheckpointId$1;
|
|
127
131
|
}
|
|
128
|
-
|
|
129
|
-
let checkpointId$1 = prevCheckpointId + 1n;
|
|
132
|
+
let checkpointId$1 = CheckpointSequence.next(cursor, fetchState.chainId);
|
|
130
133
|
checkpointIds.push(checkpointId$1);
|
|
131
134
|
checkpointChainIds.push(fetchState.chainId);
|
|
132
135
|
checkpointBlockNumbers.push(blockNumber);
|
|
133
136
|
let hash$1 = chainBeforeBatch.scannedHashes.hashByBlockNumber[blockNumber];
|
|
134
137
|
checkpointBlockHashes.push(hash$1 !== undefined ? hash$1 : null);
|
|
138
|
+
checkpointItemsCount.push(1);
|
|
135
139
|
checkpointEventsProcessed.push(1);
|
|
136
140
|
prevBlockNumber = blockNumber;
|
|
137
|
-
prevCheckpointId = checkpointId$1;
|
|
138
141
|
} else {
|
|
139
|
-
let lastIndex =
|
|
140
|
-
|
|
142
|
+
let lastIndex = checkpointItemsCount.length - 1;
|
|
143
|
+
checkpointItemsCount[lastIndex] = checkpointItemsCount[lastIndex] + 1;
|
|
144
|
+
if (isNewEvent) {
|
|
145
|
+
checkpointEventsProcessed[lastIndex] = checkpointEventsProcessed[lastIndex] + 1;
|
|
146
|
+
}
|
|
141
147
|
}
|
|
142
148
|
items.push(item);
|
|
143
149
|
}
|
|
144
150
|
totalBatchSize = totalBatchSize + chainBatchSize;
|
|
145
|
-
|
|
151
|
+
mutCountsPerChain[fetchState.chainId] = {
|
|
152
|
+
size: chainBatchSize,
|
|
153
|
+
eventsProcessed: chainEventsProcessed
|
|
154
|
+
};
|
|
146
155
|
}
|
|
147
156
|
let progressBlockNumberAfterBatch = FetchState.getProgressBlockNumberAt(fetchState, chainBatchSize);
|
|
148
157
|
let chainId$1 = fetchState.chainId;
|
|
149
158
|
let toBlockExclusive = progressBlockNumberAfterBatch + 1;
|
|
150
159
|
let fromBlockExclusive$1 = prevBlockNumber;
|
|
151
160
|
let scannedHashes$1 = chainBeforeBatch.scannedHashes;
|
|
152
|
-
let prevCheckpointId$3 = prevCheckpointId;
|
|
153
|
-
let tmp$1;
|
|
154
161
|
if (chainBeforeBatch.shouldRollbackOnReorg) {
|
|
155
|
-
let prevCheckpointId$4 = prevCheckpointId$3;
|
|
156
162
|
let blockNumbers$1 = scannedHashes$1.blockNumbers;
|
|
157
163
|
let length$1 = blockNumbers$1.length;
|
|
158
164
|
let idx$2 = seekFirstAbove(blockNumbers$1, fromBlockExclusive$1);
|
|
159
165
|
while (idx$2 < length$1 && blockNumbers$1[idx$2] < toBlockExclusive) {
|
|
160
166
|
let blockNumber$2 = blockNumbers$1[idx$2];
|
|
161
167
|
let hash$2 = scannedHashes$1.hashByBlockNumber[blockNumber$2];
|
|
162
|
-
let checkpointId$2 =
|
|
163
|
-
prevCheckpointId$4 = checkpointId$2;
|
|
168
|
+
let checkpointId$2 = CheckpointSequence.next(cursor, chainId$1);
|
|
164
169
|
checkpointIds.push(checkpointId$2);
|
|
165
170
|
checkpointChainIds.push(chainId$1);
|
|
166
171
|
checkpointBlockNumbers.push(blockNumber$2);
|
|
167
172
|
checkpointBlockHashes.push(hash$2);
|
|
173
|
+
checkpointItemsCount.push(0);
|
|
168
174
|
checkpointEventsProcessed.push(0);
|
|
169
175
|
idx$2 = idx$2 + 1;
|
|
170
176
|
};
|
|
171
|
-
tmp$1 = prevCheckpointId$4;
|
|
172
|
-
} else {
|
|
173
|
-
tmp$1 = prevCheckpointId$3;
|
|
174
177
|
}
|
|
175
|
-
prevCheckpointId = tmp$1;
|
|
176
178
|
mutProgressBlockNumberPerChain[fetchState.chainId] = progressBlockNumberAfterBatch;
|
|
177
179
|
chainIdx = chainIdx + 1;
|
|
178
180
|
};
|
|
179
181
|
return {
|
|
180
182
|
totalBatchSize: totalBatchSize,
|
|
181
183
|
items: items,
|
|
182
|
-
progressedChainsById: getProgressedChainsById(chainsBeforeBatch,
|
|
183
|
-
|
|
184
|
+
progressedChainsById: getProgressedChainsById(chainsBeforeBatch, mutCountsPerChain, mutProgressBlockNumberPerChain),
|
|
185
|
+
history: history,
|
|
184
186
|
checkpointIds: checkpointIds,
|
|
185
187
|
checkpointChainIds: checkpointChainIds,
|
|
186
188
|
checkpointBlockNumbers: checkpointBlockNumbers,
|
|
187
189
|
checkpointBlockHashes: checkpointBlockHashes,
|
|
190
|
+
checkpointItemsCount: checkpointItemsCount,
|
|
188
191
|
checkpointEventsProcessed: checkpointEventsProcessed,
|
|
189
192
|
registeredAddresses: []
|
|
190
193
|
};
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
|
|
196
|
+
function checkpointFrontier(batch) {
|
|
197
|
+
let frontier = Frontier.empty();
|
|
198
|
+
batch.checkpointChainIds.forEach((chainId, index) => Frontier.set(frontier, chainId, batch.checkpointIds[index]));
|
|
199
|
+
return frontier;
|
|
200
|
+
}
|
|
194
201
|
|
|
195
202
|
function findFirstEventBlockNumber(batch, chainId) {
|
|
196
203
|
let idx = 0;
|
|
@@ -198,7 +205,7 @@ function findFirstEventBlockNumber(batch, chainId) {
|
|
|
198
205
|
let checkpointsLength = batch.checkpointIds.length;
|
|
199
206
|
while (idx < checkpointsLength && result === undefined) {
|
|
200
207
|
let checkpointChainId = batch.checkpointChainIds[idx];
|
|
201
|
-
if (checkpointChainId === chainId && batch.
|
|
208
|
+
if (checkpointChainId === chainId && batch.checkpointItemsCount[idx] > 0) {
|
|
202
209
|
result = batch.checkpointBlockNumbers[idx];
|
|
203
210
|
} else {
|
|
204
211
|
idx = idx + 1;
|
|
@@ -225,8 +232,8 @@ export {
|
|
|
225
232
|
getProgressedChainsById,
|
|
226
233
|
seekFirstAbove,
|
|
227
234
|
addReorgCheckpoints,
|
|
228
|
-
prepareBatch,
|
|
229
235
|
make,
|
|
236
|
+
checkpointFrontier,
|
|
230
237
|
findFirstEventBlockNumber,
|
|
231
238
|
findLastEventItem,
|
|
232
239
|
}
|