ponder 0.14.13 → 0.15.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/CHANGELOG.md +16 -0
- package/dist/esm/bin/commands/createViews.js +28 -11
- package/dist/esm/bin/commands/createViews.js.map +1 -1
- package/dist/esm/bin/commands/dev.js +42 -22
- package/dist/esm/bin/commands/dev.js.map +1 -1
- package/dist/esm/bin/commands/prune.js +3 -0
- package/dist/esm/bin/commands/prune.js.map +1 -1
- package/dist/esm/bin/commands/serve.js +4 -1
- package/dist/esm/bin/commands/serve.js.map +1 -1
- package/dist/esm/bin/commands/start.js +18 -6
- package/dist/esm/bin/commands/start.js.map +1 -1
- package/dist/esm/bin/isolatedController.js +200 -0
- package/dist/esm/bin/isolatedController.js.map +1 -0
- package/dist/esm/bin/isolatedWorker.js +146 -0
- package/dist/esm/bin/isolatedWorker.js.map +1 -0
- package/dist/esm/build/config.js +322 -402
- package/dist/esm/build/config.js.map +1 -1
- package/dist/esm/build/index.js +8 -11
- package/dist/esm/build/index.js.map +1 -1
- package/dist/esm/build/pre.js +1 -4
- package/dist/esm/build/pre.js.map +1 -1
- package/dist/esm/build/schema.js +25 -3
- package/dist/esm/build/schema.js.map +1 -1
- package/dist/esm/client/index.js +306 -42
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/database/actions.js +264 -104
- package/dist/esm/database/actions.js.map +1 -1
- package/dist/esm/database/index.js +39 -33
- package/dist/esm/database/index.js.map +1 -1
- package/dist/esm/database/queryBuilder.js +1 -0
- package/dist/esm/database/queryBuilder.js.map +1 -1
- package/dist/esm/drizzle/index.js +11 -7
- package/dist/esm/drizzle/index.js.map +1 -1
- package/dist/esm/drizzle/onchain.js +18 -0
- package/dist/esm/drizzle/onchain.js.map +1 -1
- package/dist/esm/indexing/client.js +32 -25
- package/dist/esm/indexing/client.js.map +1 -1
- package/dist/esm/indexing/index.js +110 -178
- package/dist/esm/indexing/index.js.map +1 -1
- package/dist/esm/indexing/profile.js +1 -1
- package/dist/esm/indexing/profile.js.map +1 -1
- package/dist/esm/indexing-store/cache.js +196 -274
- package/dist/esm/indexing-store/cache.js.map +1 -1
- package/dist/esm/indexing-store/historical.js +17 -13
- package/dist/esm/indexing-store/historical.js.map +1 -1
- package/dist/esm/indexing-store/index.js +10 -1
- package/dist/esm/indexing-store/index.js.map +1 -1
- package/dist/esm/indexing-store/profile.js +3 -3
- package/dist/esm/indexing-store/profile.js.map +1 -1
- package/dist/esm/indexing-store/realtime.js +27 -2
- package/dist/esm/indexing-store/realtime.js.map +1 -1
- package/dist/esm/internal/errors.js +28 -0
- package/dist/esm/internal/errors.js.map +1 -1
- package/dist/esm/internal/metrics.js +279 -82
- package/dist/esm/internal/metrics.js.map +1 -1
- package/dist/esm/internal/options.js +1 -0
- package/dist/esm/internal/options.js.map +1 -1
- package/dist/esm/internal/telemetry.js +1 -1
- package/dist/esm/internal/telemetry.js.map +1 -1
- package/dist/esm/rpc/http.js +130 -0
- package/dist/esm/rpc/http.js.map +1 -0
- package/dist/esm/rpc/index.js +38 -7
- package/dist/esm/rpc/index.js.map +1 -1
- package/dist/esm/runtime/events.js +179 -212
- package/dist/esm/runtime/events.js.map +1 -1
- package/dist/esm/runtime/filter.js +71 -0
- package/dist/esm/runtime/filter.js.map +1 -1
- package/dist/esm/runtime/fragments.js +78 -73
- package/dist/esm/runtime/fragments.js.map +1 -1
- package/dist/esm/runtime/historical.js +306 -130
- package/dist/esm/runtime/historical.js.map +1 -1
- package/dist/esm/runtime/index.js +183 -58
- package/dist/esm/runtime/index.js.map +1 -1
- package/dist/esm/runtime/isolated.js +462 -0
- package/dist/esm/runtime/isolated.js.map +1 -0
- package/dist/esm/runtime/multichain.js +80 -73
- package/dist/esm/runtime/multichain.js.map +1 -1
- package/dist/esm/runtime/omnichain.js +82 -75
- package/dist/esm/runtime/omnichain.js.map +1 -1
- package/dist/esm/runtime/realtime.js +198 -66
- package/dist/esm/runtime/realtime.js.map +1 -1
- package/dist/esm/sync-historical/index.js +416 -457
- package/dist/esm/sync-historical/index.js.map +1 -1
- package/dist/esm/sync-realtime/bloom.js +3 -3
- package/dist/esm/sync-realtime/bloom.js.map +1 -1
- package/dist/esm/sync-realtime/index.js +27 -46
- package/dist/esm/sync-realtime/index.js.map +1 -1
- package/dist/esm/sync-store/index.js +112 -63
- package/dist/esm/sync-store/index.js.map +1 -1
- package/dist/esm/utils/abi.js +20 -32
- package/dist/esm/utils/abi.js.map +1 -1
- package/dist/esm/utils/chunk.js +8 -0
- package/dist/esm/utils/chunk.js.map +1 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js +19 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js.map +1 -0
- package/dist/esm/{client/parse.js → utils/sql-parse.js} +94 -80
- package/dist/esm/utils/sql-parse.js.map +1 -0
- package/dist/types/bin/commands/createViews.d.ts.map +1 -1
- package/dist/types/bin/commands/dev.d.ts.map +1 -1
- package/dist/types/bin/commands/prune.d.ts.map +1 -1
- package/dist/types/bin/commands/serve.d.ts.map +1 -1
- package/dist/types/bin/commands/start.d.ts.map +1 -1
- package/dist/types/bin/isolatedController.d.ts +13 -0
- package/dist/types/bin/isolatedController.d.ts.map +1 -0
- package/dist/types/bin/isolatedWorker.d.ts +9 -0
- package/dist/types/bin/isolatedWorker.d.ts.map +1 -0
- package/dist/types/build/config.d.ts +29 -11
- package/dist/types/build/config.d.ts.map +1 -1
- package/dist/types/build/index.d.ts +3 -2
- package/dist/types/build/index.d.ts.map +1 -1
- package/dist/types/build/pre.d.ts +1 -1
- package/dist/types/build/pre.d.ts.map +1 -1
- package/dist/types/build/schema.d.ts +5 -3
- package/dist/types/build/schema.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/config/index.d.ts +3 -3
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/database/actions.d.ts +53 -7
- package/dist/types/database/actions.d.ts.map +1 -1
- package/dist/types/database/index.d.ts +21 -21
- package/dist/types/database/index.d.ts.map +1 -1
- package/dist/types/database/queryBuilder.d.ts.map +1 -1
- package/dist/types/drizzle/index.d.ts +4 -5
- package/dist/types/drizzle/index.d.ts.map +1 -1
- package/dist/types/drizzle/onchain.d.ts +6 -0
- package/dist/types/drizzle/onchain.d.ts.map +1 -1
- package/dist/types/indexing/client.d.ts.map +1 -1
- package/dist/types/indexing/index.d.ts +2 -5
- package/dist/types/indexing/index.d.ts.map +1 -1
- package/dist/types/indexing-store/cache.d.ts +3 -2
- package/dist/types/indexing-store/cache.d.ts.map +1 -1
- package/dist/types/indexing-store/historical.d.ts +2 -1
- package/dist/types/indexing-store/historical.d.ts.map +1 -1
- package/dist/types/indexing-store/index.d.ts +1 -0
- package/dist/types/indexing-store/index.d.ts.map +1 -1
- package/dist/types/indexing-store/realtime.d.ts +2 -1
- package/dist/types/indexing-store/realtime.d.ts.map +1 -1
- package/dist/types/internal/errors.d.ts +5 -0
- package/dist/types/internal/errors.d.ts.map +1 -1
- package/dist/types/internal/metrics.d.ts +21 -0
- package/dist/types/internal/metrics.d.ts.map +1 -1
- package/dist/types/internal/options.d.ts +2 -0
- package/dist/types/internal/options.d.ts.map +1 -1
- package/dist/types/internal/types.d.ts +66 -58
- package/dist/types/internal/types.d.ts.map +1 -1
- package/dist/types/rpc/http.d.ts +17 -0
- package/dist/types/rpc/http.d.ts.map +1 -0
- package/dist/types/rpc/index.d.ts.map +1 -1
- package/dist/types/runtime/events.d.ts +4 -4
- package/dist/types/runtime/events.d.ts.map +1 -1
- package/dist/types/runtime/filter.d.ts +5 -1
- package/dist/types/runtime/filter.d.ts.map +1 -1
- package/dist/types/runtime/fragments.d.ts +4 -3
- package/dist/types/runtime/fragments.d.ts.map +1 -1
- package/dist/types/runtime/historical.d.ts +29 -13
- package/dist/types/runtime/historical.d.ts.map +1 -1
- package/dist/types/runtime/index.d.ts +49 -6
- package/dist/types/runtime/index.d.ts.map +1 -1
- package/dist/types/runtime/init.d.ts +5 -5
- package/dist/types/runtime/init.d.ts.map +1 -1
- package/dist/types/runtime/isolated.d.ts +14 -0
- package/dist/types/runtime/isolated.d.ts.map +1 -0
- package/dist/types/runtime/multichain.d.ts.map +1 -1
- package/dist/types/runtime/omnichain.d.ts.map +1 -1
- package/dist/types/runtime/realtime.d.ts +21 -10
- package/dist/types/runtime/realtime.d.ts.map +1 -1
- package/dist/types/sync-historical/index.d.ts +18 -8
- package/dist/types/sync-historical/index.d.ts.map +1 -1
- package/dist/types/sync-realtime/bloom.d.ts.map +1 -1
- package/dist/types/sync-realtime/index.d.ts +2 -2
- package/dist/types/sync-realtime/index.d.ts.map +1 -1
- package/dist/types/sync-store/index.d.ts +9 -9
- package/dist/types/sync-store/index.d.ts.map +1 -1
- package/dist/types/utils/abi.d.ts +3 -34
- package/dist/types/utils/abi.d.ts.map +1 -1
- package/dist/types/utils/chunk.d.ts +2 -0
- package/dist/types/utils/chunk.d.ts.map +1 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts +8 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts.map +1 -0
- package/dist/types/utils/sql-parse.d.ts +21 -0
- package/dist/types/utils/sql-parse.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/bin/commands/createViews.ts +35 -15
- package/src/bin/commands/dev.ts +43 -21
- package/src/bin/commands/prune.ts +6 -0
- package/src/bin/commands/serve.ts +4 -1
- package/src/bin/commands/start.ts +20 -5
- package/src/bin/isolatedController.ts +300 -0
- package/src/bin/isolatedWorker.ts +192 -0
- package/src/build/config.ts +570 -632
- package/src/build/index.ts +14 -14
- package/src/build/pre.ts +1 -4
- package/src/build/schema.ts +49 -4
- package/src/client/index.ts +386 -48
- package/src/config/index.ts +3 -3
- package/src/database/actions.ts +469 -120
- package/src/database/index.ts +85 -58
- package/src/database/queryBuilder.ts +1 -0
- package/src/drizzle/index.ts +15 -7
- package/src/drizzle/onchain.ts +19 -0
- package/src/indexing/client.ts +38 -25
- package/src/indexing/index.ts +137 -230
- package/src/indexing/profile.ts +1 -1
- package/src/indexing-store/cache.ts +285 -414
- package/src/indexing-store/historical.ts +20 -10
- package/src/indexing-store/index.ts +16 -0
- package/src/indexing-store/profile.ts +3 -3
- package/src/indexing-store/realtime.ts +28 -0
- package/src/internal/errors.ts +26 -0
- package/src/internal/metrics.ts +341 -111
- package/src/internal/options.ts +4 -0
- package/src/internal/telemetry.ts +1 -1
- package/src/internal/types.ts +70 -87
- package/src/rpc/http.ts +164 -0
- package/src/rpc/index.ts +39 -7
- package/src/runtime/events.ts +195 -240
- package/src/runtime/filter.ts +85 -1
- package/src/runtime/fragments.ts +109 -113
- package/src/runtime/historical.ts +467 -189
- package/src/runtime/index.ts +337 -69
- package/src/runtime/init.ts +5 -5
- package/src/runtime/isolated.ts +768 -0
- package/src/runtime/multichain.ts +137 -102
- package/src/runtime/omnichain.ts +138 -106
- package/src/runtime/realtime.ts +322 -123
- package/src/sync-historical/index.ts +556 -692
- package/src/sync-realtime/bloom.ts +7 -3
- package/src/sync-realtime/index.ts +31 -46
- package/src/sync-store/index.ts +189 -95
- package/src/utils/abi.ts +33 -90
- package/src/utils/chunk.ts +7 -0
- package/src/utils/promiseAllSettledWithThrow.ts +27 -0
- package/src/{client/parse.ts → utils/sql-parse.ts} +100 -90
- package/dist/esm/client/parse.js.map +0 -1
- package/dist/types/client/parse.d.ts +0 -14
- package/dist/types/client/parse.d.ts.map +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
|
+
import type { Database } from "@/database/index.js";
|
|
1
2
|
import type { Common } from "@/internal/common.js";
|
|
2
3
|
import { ShutdownError } from "@/internal/errors.js";
|
|
3
4
|
import type {
|
|
4
5
|
Chain,
|
|
5
6
|
CrashRecoveryCheckpoint,
|
|
6
7
|
Event,
|
|
8
|
+
EventCallback,
|
|
7
9
|
IndexingBuild,
|
|
8
10
|
RawEvent,
|
|
9
|
-
Source,
|
|
10
11
|
SyncBlock,
|
|
11
12
|
} from "@/internal/types.js";
|
|
12
13
|
import { _eth_getBlockByNumber } from "@/rpc/actions.js";
|
|
13
14
|
import type { Rpc } from "@/rpc/index.js";
|
|
14
15
|
import { buildEvents, decodeEvents } from "@/runtime/events.js";
|
|
15
|
-
import { isAddressFactory } from "@/runtime/filter.js";
|
|
16
16
|
import { createHistoricalSync } from "@/sync-historical/index.js";
|
|
17
|
-
import type
|
|
17
|
+
import { type SyncStore, createSyncStore } from "@/sync-store/index.js";
|
|
18
18
|
import {
|
|
19
19
|
MAX_CHECKPOINT,
|
|
20
20
|
ZERO_CHECKPOINT,
|
|
@@ -22,22 +22,25 @@ import {
|
|
|
22
22
|
encodeCheckpoint,
|
|
23
23
|
min,
|
|
24
24
|
} from "@/utils/checkpoint.js";
|
|
25
|
+
import { estimate } from "@/utils/estimate.js";
|
|
25
26
|
import { formatPercentage } from "@/utils/format.js";
|
|
26
27
|
import {
|
|
27
28
|
bufferAsyncGenerator,
|
|
29
|
+
createCallbackGenerator,
|
|
28
30
|
mergeAsyncGenerators,
|
|
29
31
|
} from "@/utils/generators.js";
|
|
30
|
-
import {
|
|
31
|
-
type Interval,
|
|
32
|
-
intervalDifference,
|
|
33
|
-
intervalIntersectionMany,
|
|
34
|
-
intervalSum,
|
|
35
|
-
intervalUnion,
|
|
36
|
-
} from "@/utils/interval.js";
|
|
32
|
+
import { type Interval, intervalSum } from "@/utils/interval.js";
|
|
37
33
|
import { partition } from "@/utils/partition.js";
|
|
34
|
+
import { promiseWithResolvers } from "@/utils/promiseWithResolvers.js";
|
|
38
35
|
import { startClock } from "@/utils/timer.js";
|
|
39
36
|
import { hexToNumber } from "viem";
|
|
40
|
-
import
|
|
37
|
+
import {
|
|
38
|
+
type CachedIntervals,
|
|
39
|
+
type ChildAddresses,
|
|
40
|
+
type SyncProgress,
|
|
41
|
+
getRequiredIntervals,
|
|
42
|
+
getRequiredIntervalsWithFilters,
|
|
43
|
+
} from "./index.js";
|
|
41
44
|
import { initEventGenerator, initRefetchEvents } from "./init.js";
|
|
42
45
|
import { getOmnichainCheckpoint } from "./omnichain.js";
|
|
43
46
|
|
|
@@ -45,7 +48,7 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
45
48
|
common: Common;
|
|
46
49
|
indexingBuild: Pick<
|
|
47
50
|
IndexingBuild,
|
|
48
|
-
"
|
|
51
|
+
"eventCallbacks" | "chains" | "rpcs" | "finalizedBlocks"
|
|
49
52
|
>;
|
|
50
53
|
crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
|
|
51
54
|
perChainSync: Map<
|
|
@@ -56,7 +59,7 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
56
59
|
cachedIntervals: CachedIntervals;
|
|
57
60
|
}
|
|
58
61
|
>;
|
|
59
|
-
|
|
62
|
+
database: Database;
|
|
60
63
|
}): AsyncGenerator<
|
|
61
64
|
| {
|
|
62
65
|
type: "events";
|
|
@@ -84,9 +87,10 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
84
87
|
params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
|
|
85
88
|
]!;
|
|
86
89
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
const eventCallbacks =
|
|
91
|
+
params.indexingBuild.eventCallbacks[
|
|
92
|
+
params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
|
|
93
|
+
]!;
|
|
90
94
|
|
|
91
95
|
const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
|
|
92
96
|
({ chainId }) => chainId === chain.id,
|
|
@@ -121,7 +125,10 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
121
125
|
) {
|
|
122
126
|
from = crashRecoveryCheckpoint;
|
|
123
127
|
} else {
|
|
124
|
-
const fromBlock = await
|
|
128
|
+
const fromBlock = await createSyncStore({
|
|
129
|
+
common: params.common,
|
|
130
|
+
qb: params.database.syncQB,
|
|
131
|
+
}).getSafeCrashRecoveryBlock({
|
|
125
132
|
chainId: chain.id,
|
|
126
133
|
timestamp: Number(
|
|
127
134
|
decodeCheckpoint(crashRecoveryCheckpoint).blockTimestamp,
|
|
@@ -147,12 +154,12 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
147
154
|
|
|
148
155
|
const events = pendingEvents.filter(
|
|
149
156
|
(event) =>
|
|
150
|
-
event.
|
|
157
|
+
event.chain.id === chain.id && event.checkpoint <= omnichainTo,
|
|
151
158
|
);
|
|
152
159
|
|
|
153
160
|
pendingEvents = pendingEvents.filter(
|
|
154
161
|
(event) =>
|
|
155
|
-
(event.
|
|
162
|
+
(event.chain.id === chain.id &&
|
|
156
163
|
event.checkpoint <= omnichainTo) === false,
|
|
157
164
|
);
|
|
158
165
|
|
|
@@ -193,7 +200,7 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
193
200
|
indexingBuild: params.indexingBuild,
|
|
194
201
|
chain,
|
|
195
202
|
rpc,
|
|
196
|
-
|
|
203
|
+
eventCallbacks,
|
|
197
204
|
childAddresses,
|
|
198
205
|
syncProgress,
|
|
199
206
|
cachedIntervals,
|
|
@@ -204,7 +211,7 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
204
211
|
params.common.options.syncEventsQuerySize /
|
|
205
212
|
(params.indexingBuild.chains.length + 1),
|
|
206
213
|
) + 6,
|
|
207
|
-
|
|
214
|
+
database: params.database,
|
|
208
215
|
isCatchup,
|
|
209
216
|
});
|
|
210
217
|
|
|
@@ -215,7 +222,12 @@ export async function* getHistoricalEventsOmnichain(params: {
|
|
|
215
222
|
} of eventGenerator) {
|
|
216
223
|
const endClock = startClock();
|
|
217
224
|
|
|
218
|
-
let events = decodeEvents(
|
|
225
|
+
let events = decodeEvents(
|
|
226
|
+
params.common,
|
|
227
|
+
chain,
|
|
228
|
+
eventCallbacks,
|
|
229
|
+
rawEvents,
|
|
230
|
+
);
|
|
219
231
|
|
|
220
232
|
params.common.logger.trace({
|
|
221
233
|
msg: "Decoded events",
|
|
@@ -371,7 +383,7 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
371
383
|
common: Common;
|
|
372
384
|
indexingBuild: Pick<
|
|
373
385
|
IndexingBuild,
|
|
374
|
-
"
|
|
386
|
+
"eventCallbacks" | "chains" | "rpcs" | "finalizedBlocks"
|
|
375
387
|
>;
|
|
376
388
|
crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
|
|
377
389
|
perChainSync: Map<
|
|
@@ -382,7 +394,7 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
382
394
|
cachedIntervals: CachedIntervals;
|
|
383
395
|
}
|
|
384
396
|
>;
|
|
385
|
-
|
|
397
|
+
database: Database;
|
|
386
398
|
}) {
|
|
387
399
|
let isCatchup = false;
|
|
388
400
|
let lastUnfinalizedRefetch = Date.now();
|
|
@@ -399,9 +411,10 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
399
411
|
params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
|
|
400
412
|
]!;
|
|
401
413
|
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
414
|
+
const eventCallbacks =
|
|
415
|
+
params.indexingBuild.eventCallbacks[
|
|
416
|
+
params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
|
|
417
|
+
]!;
|
|
405
418
|
|
|
406
419
|
const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
|
|
407
420
|
({ chainId }) => chainId === chain.id,
|
|
@@ -426,7 +439,10 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
426
439
|
) {
|
|
427
440
|
from = crashRecoveryCheckpoint;
|
|
428
441
|
} else {
|
|
429
|
-
const fromBlock = await
|
|
442
|
+
const fromBlock = await createSyncStore({
|
|
443
|
+
common: params.common,
|
|
444
|
+
qb: params.database.syncQB,
|
|
445
|
+
}).getSafeCrashRecoveryBlock({
|
|
430
446
|
chainId: chain.id,
|
|
431
447
|
timestamp: Number(
|
|
432
448
|
decodeCheckpoint(crashRecoveryCheckpoint).blockTimestamp,
|
|
@@ -472,7 +488,7 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
472
488
|
indexingBuild: params.indexingBuild,
|
|
473
489
|
chain,
|
|
474
490
|
rpc,
|
|
475
|
-
|
|
491
|
+
eventCallbacks,
|
|
476
492
|
childAddresses,
|
|
477
493
|
syncProgress,
|
|
478
494
|
cachedIntervals,
|
|
@@ -483,7 +499,7 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
483
499
|
params.common.options.syncEventsQuerySize /
|
|
484
500
|
(params.indexingBuild.chains.length + 1),
|
|
485
501
|
) + 6,
|
|
486
|
-
|
|
502
|
+
database: params.database,
|
|
487
503
|
isCatchup,
|
|
488
504
|
});
|
|
489
505
|
|
|
@@ -494,7 +510,12 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
494
510
|
} of eventGenerator) {
|
|
495
511
|
const endClock = startClock();
|
|
496
512
|
|
|
497
|
-
let events = decodeEvents(
|
|
513
|
+
let events = decodeEvents(
|
|
514
|
+
params.common,
|
|
515
|
+
chain,
|
|
516
|
+
eventCallbacks,
|
|
517
|
+
rawEvents,
|
|
518
|
+
);
|
|
498
519
|
|
|
499
520
|
params.common.logger.trace({
|
|
500
521
|
msg: "Decoded events",
|
|
@@ -614,25 +635,223 @@ export async function* getHistoricalEventsMultichain(params: {
|
|
|
614
635
|
}
|
|
615
636
|
}
|
|
616
637
|
|
|
638
|
+
export async function* getHistoricalEventsIsolated(params: {
|
|
639
|
+
common: Common;
|
|
640
|
+
indexingBuild: Pick<
|
|
641
|
+
IndexingBuild,
|
|
642
|
+
"eventCallbacks" | "chains" | "rpcs" | "finalizedBlocks"
|
|
643
|
+
>;
|
|
644
|
+
crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
|
|
645
|
+
chain: Chain;
|
|
646
|
+
syncProgress: SyncProgress;
|
|
647
|
+
childAddresses: ChildAddresses;
|
|
648
|
+
cachedIntervals: CachedIntervals;
|
|
649
|
+
database: Database;
|
|
650
|
+
}) {
|
|
651
|
+
let isCatchup = false;
|
|
652
|
+
let lastUnfinalizedRefetch = Date.now();
|
|
653
|
+
let cursor: string | undefined;
|
|
654
|
+
|
|
655
|
+
while (true) {
|
|
656
|
+
const rpc =
|
|
657
|
+
params.indexingBuild.rpcs[
|
|
658
|
+
params.indexingBuild.chains.findIndex((c) => c.id === params.chain.id)
|
|
659
|
+
]!;
|
|
660
|
+
|
|
661
|
+
const eventCallbacks =
|
|
662
|
+
params.indexingBuild.eventCallbacks[
|
|
663
|
+
params.indexingBuild.chains.findIndex((c) => c.id === params.chain.id)
|
|
664
|
+
]!;
|
|
665
|
+
|
|
666
|
+
const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
|
|
667
|
+
({ chainId }) => chainId === params.chain.id,
|
|
668
|
+
)?.checkpoint;
|
|
669
|
+
|
|
670
|
+
const to = min(
|
|
671
|
+
params.syncProgress.getCheckpoint({ tag: "finalized" }),
|
|
672
|
+
params.syncProgress.getCheckpoint({ tag: "end" }),
|
|
673
|
+
);
|
|
674
|
+
let from: string;
|
|
675
|
+
|
|
676
|
+
if (isCatchup === false) {
|
|
677
|
+
// In order to speed up the "extract" phase when there is a crash recovery,
|
|
678
|
+
// the beginning cursor is moved forwards. This only works when `crashRecoveryCheckpoint`
|
|
679
|
+
// is defined.
|
|
680
|
+
|
|
681
|
+
if (crashRecoveryCheckpoint === undefined) {
|
|
682
|
+
from = params.syncProgress.getCheckpoint({ tag: "start" });
|
|
683
|
+
} else if (
|
|
684
|
+
Number(decodeCheckpoint(crashRecoveryCheckpoint).chainId) ===
|
|
685
|
+
params.chain.id
|
|
686
|
+
) {
|
|
687
|
+
from = crashRecoveryCheckpoint;
|
|
688
|
+
} else {
|
|
689
|
+
from = params.syncProgress.getCheckpoint({ tag: "start" });
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
from = encodeCheckpoint({
|
|
693
|
+
...ZERO_CHECKPOINT,
|
|
694
|
+
blockTimestamp: decodeCheckpoint(cursor!).blockTimestamp,
|
|
695
|
+
chainId: decodeCheckpoint(cursor!).chainId,
|
|
696
|
+
blockNumber: decodeCheckpoint(cursor!).blockNumber + 1n,
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
if (from > to) return;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
params.common.logger.info({
|
|
703
|
+
msg: "Started backfill indexing",
|
|
704
|
+
chain: params.chain.name,
|
|
705
|
+
chain_id: params.chain.id,
|
|
706
|
+
block_range: JSON.stringify([
|
|
707
|
+
Number(decodeCheckpoint(from).blockNumber),
|
|
708
|
+
Number(decodeCheckpoint(to).blockNumber),
|
|
709
|
+
]),
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
const eventGenerator = await initEventGenerator({
|
|
713
|
+
common: params.common,
|
|
714
|
+
indexingBuild: params.indexingBuild,
|
|
715
|
+
chain: params.chain,
|
|
716
|
+
rpc,
|
|
717
|
+
eventCallbacks,
|
|
718
|
+
childAddresses: params.childAddresses,
|
|
719
|
+
syncProgress: params.syncProgress,
|
|
720
|
+
cachedIntervals: params.cachedIntervals,
|
|
721
|
+
from,
|
|
722
|
+
to,
|
|
723
|
+
limit:
|
|
724
|
+
Math.round(
|
|
725
|
+
params.common.options.syncEventsQuerySize /
|
|
726
|
+
(params.indexingBuild.chains.length + 1),
|
|
727
|
+
) + 6,
|
|
728
|
+
database: params.database,
|
|
729
|
+
isCatchup,
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
for await (const {
|
|
733
|
+
events: rawEvents,
|
|
734
|
+
checkpoint,
|
|
735
|
+
blockRange,
|
|
736
|
+
} of eventGenerator) {
|
|
737
|
+
const endClock = startClock();
|
|
738
|
+
|
|
739
|
+
let events = decodeEvents(
|
|
740
|
+
params.common,
|
|
741
|
+
params.chain,
|
|
742
|
+
eventCallbacks,
|
|
743
|
+
rawEvents,
|
|
744
|
+
);
|
|
745
|
+
|
|
746
|
+
params.common.logger.trace({
|
|
747
|
+
msg: "Decoded events",
|
|
748
|
+
chain: params.chain.name,
|
|
749
|
+
chain_id: params.chain.id,
|
|
750
|
+
event_count: events.length,
|
|
751
|
+
duration: endClock(),
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
params.common.metrics.ponder_historical_extract_duration.inc(
|
|
755
|
+
{ step: "decode" },
|
|
756
|
+
endClock(),
|
|
757
|
+
);
|
|
758
|
+
|
|
759
|
+
// Removes events that have a checkpoint earlier than (or equal to)
|
|
760
|
+
// the crash recovery checkpoint.
|
|
761
|
+
|
|
762
|
+
if (crashRecoveryCheckpoint) {
|
|
763
|
+
const [left, right] = partition(
|
|
764
|
+
events,
|
|
765
|
+
(event) => event.checkpoint <= crashRecoveryCheckpoint,
|
|
766
|
+
);
|
|
767
|
+
events = right;
|
|
768
|
+
|
|
769
|
+
if (left.length > 0) {
|
|
770
|
+
params.common.logger.trace({
|
|
771
|
+
msg: "Filtered events before crash recovery checkpoint",
|
|
772
|
+
chain: params.chain.name,
|
|
773
|
+
chain_id: params.chain.id,
|
|
774
|
+
event_count: left.length,
|
|
775
|
+
checkpoint: crashRecoveryCheckpoint,
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
yield { chainId: params.chain.id, events, checkpoint, blockRange };
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
cursor = to;
|
|
784
|
+
|
|
785
|
+
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
lastUnfinalizedRefetch = Date.now();
|
|
789
|
+
|
|
790
|
+
const context = {
|
|
791
|
+
logger: params.common.logger.child({ action: "refetch_finalized_block" }),
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
const endClock = startClock();
|
|
795
|
+
|
|
796
|
+
const finalizedBlock = await _eth_getBlockByNumber(
|
|
797
|
+
rpc,
|
|
798
|
+
{ blockTag: "latest" },
|
|
799
|
+
context,
|
|
800
|
+
).then((latest) =>
|
|
801
|
+
_eth_getBlockByNumber(
|
|
802
|
+
rpc,
|
|
803
|
+
{
|
|
804
|
+
blockNumber: Math.max(
|
|
805
|
+
hexToNumber(latest.number) - params.chain.finalityBlockCount,
|
|
806
|
+
0,
|
|
807
|
+
),
|
|
808
|
+
},
|
|
809
|
+
context,
|
|
810
|
+
),
|
|
811
|
+
);
|
|
812
|
+
|
|
813
|
+
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
|
|
814
|
+
params.common.logger.debug({
|
|
815
|
+
msg: "Refetched finalized block for backfill cutover",
|
|
816
|
+
chain: params.chain.name,
|
|
817
|
+
chain_id: params.chain.id,
|
|
818
|
+
finalized_block: finalizedBlockNumber,
|
|
819
|
+
duration: endClock(),
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
if (
|
|
823
|
+
hexToNumber(finalizedBlock.number) -
|
|
824
|
+
hexToNumber(params.syncProgress.finalized.number) <=
|
|
825
|
+
params.chain.finalityBlockCount
|
|
826
|
+
) {
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
params.syncProgress.finalized = finalizedBlock;
|
|
831
|
+
isCatchup = true;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
617
835
|
export async function refetchHistoricalEvents(params: {
|
|
618
836
|
common: Common;
|
|
619
|
-
indexingBuild: Pick<IndexingBuild, "
|
|
837
|
+
indexingBuild: Pick<IndexingBuild, "eventCallbacks" | "chains">;
|
|
620
838
|
perChainSync: Map<Chain, { childAddresses: ChildAddresses }>;
|
|
621
839
|
events: Event[];
|
|
622
840
|
syncStore: SyncStore;
|
|
623
841
|
}): Promise<Event[]> {
|
|
624
842
|
const events: Event[] = new Array(params.events.length);
|
|
625
843
|
|
|
626
|
-
for (const chain of
|
|
844
|
+
for (const chain of params.indexingBuild.chains) {
|
|
627
845
|
const { childAddresses } = params.perChainSync.get(chain)!;
|
|
628
846
|
|
|
629
847
|
// Note: All filters are refetched, no matter if they are resolved or not.
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
848
|
+
const eventCallbacks =
|
|
849
|
+
params.indexingBuild.eventCallbacks[
|
|
850
|
+
params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
|
|
851
|
+
]!;
|
|
633
852
|
|
|
634
853
|
const chainEvents = params.events.filter(
|
|
635
|
-
(event) => event.
|
|
854
|
+
(event) => event.chain.id === chain.id,
|
|
636
855
|
);
|
|
637
856
|
|
|
638
857
|
if (chainEvents.length === 0) continue;
|
|
@@ -641,14 +860,19 @@ export async function refetchHistoricalEvents(params: {
|
|
|
641
860
|
common: params.common,
|
|
642
861
|
chain,
|
|
643
862
|
childAddresses,
|
|
644
|
-
|
|
863
|
+
eventCallbacks,
|
|
645
864
|
events: chainEvents,
|
|
646
865
|
syncStore: params.syncStore,
|
|
647
866
|
});
|
|
648
867
|
|
|
649
868
|
const endClock = startClock();
|
|
650
869
|
|
|
651
|
-
const refetchedEvents = decodeEvents(
|
|
870
|
+
const refetchedEvents = decodeEvents(
|
|
871
|
+
params.common,
|
|
872
|
+
chain,
|
|
873
|
+
eventCallbacks,
|
|
874
|
+
rawEvents,
|
|
875
|
+
);
|
|
652
876
|
|
|
653
877
|
params.common.logger.trace({
|
|
654
878
|
msg: "Decoded events",
|
|
@@ -667,7 +891,7 @@ export async function refetchHistoricalEvents(params: {
|
|
|
667
891
|
let j = 0;
|
|
668
892
|
|
|
669
893
|
while (i < params.events.length && j < refetchedEvents.length) {
|
|
670
|
-
if (params.events[i]?.
|
|
894
|
+
if (params.events[i]?.chain.id === chain.id) {
|
|
671
895
|
events[i] = refetchedEvents[j]!;
|
|
672
896
|
i++;
|
|
673
897
|
j++;
|
|
@@ -684,7 +908,7 @@ export async function refetchLocalEvents(params: {
|
|
|
684
908
|
common: Common;
|
|
685
909
|
chain: Chain;
|
|
686
910
|
childAddresses: ChildAddresses;
|
|
687
|
-
|
|
911
|
+
eventCallbacks: EventCallback[];
|
|
688
912
|
events: Event[];
|
|
689
913
|
syncStore: SyncStore;
|
|
690
914
|
}): Promise<RawEvent[]> {
|
|
@@ -707,7 +931,7 @@ export async function refetchLocalEvents(params: {
|
|
|
707
931
|
traces,
|
|
708
932
|
cursor: queryCursor,
|
|
709
933
|
} = await params.syncStore.getEventData({
|
|
710
|
-
filters: params.
|
|
934
|
+
filters: params.eventCallbacks.map(({ filter }) => filter),
|
|
711
935
|
fromBlock: cursor,
|
|
712
936
|
toBlock,
|
|
713
937
|
chainId: params.chain.id,
|
|
@@ -716,7 +940,7 @@ export async function refetchLocalEvents(params: {
|
|
|
716
940
|
|
|
717
941
|
const endClock = startClock();
|
|
718
942
|
const rawEvents = buildEvents({
|
|
719
|
-
|
|
943
|
+
eventCallbacks: params.eventCallbacks,
|
|
720
944
|
blocks,
|
|
721
945
|
logs,
|
|
722
946
|
transactions,
|
|
@@ -767,16 +991,21 @@ export async function* getLocalEventGenerator(params: {
|
|
|
767
991
|
common: Common;
|
|
768
992
|
chain: Chain;
|
|
769
993
|
rpc: Rpc;
|
|
770
|
-
|
|
994
|
+
eventCallbacks: EventCallback[];
|
|
771
995
|
childAddresses: ChildAddresses;
|
|
772
996
|
syncProgress: SyncProgress;
|
|
773
997
|
cachedIntervals: CachedIntervals;
|
|
774
998
|
from: string;
|
|
775
999
|
to: string;
|
|
776
1000
|
limit: number;
|
|
777
|
-
|
|
1001
|
+
database: Database;
|
|
778
1002
|
isCatchup: boolean;
|
|
779
1003
|
}) {
|
|
1004
|
+
const syncStore = createSyncStore({
|
|
1005
|
+
common: params.common,
|
|
1006
|
+
qb: params.database.syncQB,
|
|
1007
|
+
});
|
|
1008
|
+
|
|
780
1009
|
const fromBlock = Number(decodeCheckpoint(params.from).blockNumber);
|
|
781
1010
|
const toBlock = Number(decodeCheckpoint(params.to).blockNumber);
|
|
782
1011
|
let cursor = fromBlock;
|
|
@@ -797,8 +1026,8 @@ export async function* getLocalEventGenerator(params: {
|
|
|
797
1026
|
transactionReceipts,
|
|
798
1027
|
traces,
|
|
799
1028
|
cursor: queryCursor,
|
|
800
|
-
} = await
|
|
801
|
-
filters: params.
|
|
1029
|
+
} = await syncStore.getEventData({
|
|
1030
|
+
filters: params.eventCallbacks.map(({ filter }) => filter),
|
|
802
1031
|
fromBlock: cursor,
|
|
803
1032
|
toBlock: Math.min(syncCursor, toBlock),
|
|
804
1033
|
chainId: params.chain.id,
|
|
@@ -807,7 +1036,7 @@ export async function* getLocalEventGenerator(params: {
|
|
|
807
1036
|
|
|
808
1037
|
const endClock = startClock();
|
|
809
1038
|
const events = buildEvents({
|
|
810
|
-
|
|
1039
|
+
eventCallbacks: params.eventCallbacks,
|
|
811
1040
|
blocks,
|
|
812
1041
|
logs,
|
|
813
1042
|
transactions,
|
|
@@ -864,17 +1093,17 @@ export async function* getLocalSyncGenerator(params: {
|
|
|
864
1093
|
common: Common;
|
|
865
1094
|
chain: Chain;
|
|
866
1095
|
rpc: Rpc;
|
|
867
|
-
|
|
1096
|
+
eventCallbacks: EventCallback[];
|
|
868
1097
|
syncProgress: SyncProgress;
|
|
869
1098
|
childAddresses: ChildAddresses;
|
|
870
1099
|
cachedIntervals: CachedIntervals;
|
|
871
|
-
|
|
1100
|
+
database: Database;
|
|
872
1101
|
isCatchup: boolean;
|
|
873
1102
|
}) {
|
|
874
1103
|
const backfillEndClock = startClock();
|
|
875
1104
|
const label = { chain: params.chain.name };
|
|
876
1105
|
|
|
877
|
-
let
|
|
1106
|
+
let first = hexToNumber(params.syncProgress.start.number);
|
|
878
1107
|
const last =
|
|
879
1108
|
params.syncProgress.end === undefined
|
|
880
1109
|
? params.syncProgress.finalized
|
|
@@ -924,61 +1153,13 @@ export async function* getLocalSyncGenerator(params: {
|
|
|
924
1153
|
hexToNumber(last!.number),
|
|
925
1154
|
] satisfies Interval;
|
|
926
1155
|
|
|
927
|
-
const requiredIntervals =
|
|
928
|
-
params.
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
[
|
|
932
|
-
filter.fromBlock ?? 0,
|
|
933
|
-
Math.min(filter.toBlock ?? Number.POSITIVE_INFINITY, totalInterval[1]),
|
|
934
|
-
],
|
|
935
|
-
];
|
|
936
|
-
|
|
937
|
-
switch (filter.type) {
|
|
938
|
-
case "log":
|
|
939
|
-
if (isAddressFactory(filter.address)) {
|
|
940
|
-
filterIntervals.push([
|
|
941
|
-
filter.address.fromBlock ?? 0,
|
|
942
|
-
Math.min(
|
|
943
|
-
filter.address.toBlock ?? Number.POSITIVE_INFINITY,
|
|
944
|
-
totalInterval[1],
|
|
945
|
-
),
|
|
946
|
-
]);
|
|
947
|
-
}
|
|
948
|
-
break;
|
|
949
|
-
case "trace":
|
|
950
|
-
case "transaction":
|
|
951
|
-
case "transfer":
|
|
952
|
-
if (isAddressFactory(filter.fromAddress)) {
|
|
953
|
-
filterIntervals.push([
|
|
954
|
-
filter.fromAddress.fromBlock ?? 0,
|
|
955
|
-
Math.min(
|
|
956
|
-
filter.fromAddress.toBlock ?? Number.POSITIVE_INFINITY,
|
|
957
|
-
totalInterval[1],
|
|
958
|
-
),
|
|
959
|
-
]);
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
if (isAddressFactory(filter.toAddress)) {
|
|
963
|
-
filterIntervals.push([
|
|
964
|
-
filter.toAddress.fromBlock ?? 0,
|
|
965
|
-
Math.min(
|
|
966
|
-
filter.toAddress.toBlock ?? Number.POSITIVE_INFINITY,
|
|
967
|
-
totalInterval[1],
|
|
968
|
-
),
|
|
969
|
-
]);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
return intervalDifference(
|
|
974
|
-
intervalUnion(filterIntervals),
|
|
975
|
-
intervalIntersectionMany(
|
|
976
|
-
fragmentIntervals.map(({ intervals }) => intervals),
|
|
977
|
-
),
|
|
978
|
-
);
|
|
1156
|
+
const requiredIntervals = getRequiredIntervals({
|
|
1157
|
+
filters: params.eventCallbacks.map(({ filter }) => filter),
|
|
1158
|
+
interval: totalInterval,
|
|
1159
|
+
cachedIntervals: params.cachedIntervals,
|
|
979
1160
|
});
|
|
980
1161
|
|
|
981
|
-
const required = intervalSum(
|
|
1162
|
+
const required = intervalSum(requiredIntervals);
|
|
982
1163
|
const total = totalInterval[1] - totalInterval[0] + 1;
|
|
983
1164
|
|
|
984
1165
|
params.common.metrics.ponder_historical_total_blocks.set(label, total);
|
|
@@ -1025,7 +1206,7 @@ export async function* getLocalSyncGenerator(params: {
|
|
|
1025
1206
|
});
|
|
1026
1207
|
}
|
|
1027
1208
|
|
|
1028
|
-
|
|
1209
|
+
first = hexToNumber(params.syncProgress.current.number) + 1;
|
|
1029
1210
|
} else {
|
|
1030
1211
|
params.common.logger.info({
|
|
1031
1212
|
msg: "Started fetching backfill JSON-RPC data",
|
|
@@ -1037,115 +1218,212 @@ export async function* getLocalSyncGenerator(params: {
|
|
|
1037
1218
|
|
|
1038
1219
|
const historicalSync = createHistoricalSync(params);
|
|
1039
1220
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1221
|
+
const { callback: intervalCallback, generator: intervalGenerator } =
|
|
1222
|
+
createCallbackGenerator<{
|
|
1223
|
+
interval: Interval;
|
|
1224
|
+
promise: Promise<void>;
|
|
1225
|
+
}>();
|
|
1226
|
+
|
|
1227
|
+
intervalCallback({
|
|
1228
|
+
interval: [
|
|
1229
|
+
first,
|
|
1230
|
+
Math.min(first + estimateRange, hexToNumber(last.number)),
|
|
1231
|
+
],
|
|
1232
|
+
promise: Promise.resolve(),
|
|
1233
|
+
});
|
|
1049
1234
|
|
|
1235
|
+
/**
|
|
1236
|
+
* @returns `true` if any data was inserted into the database.
|
|
1237
|
+
*/
|
|
1238
|
+
async function syncInterval({
|
|
1239
|
+
interval,
|
|
1240
|
+
promise,
|
|
1241
|
+
}: { interval: Interval; promise: Promise<void> }): Promise<boolean> {
|
|
1050
1242
|
const endClock = startClock();
|
|
1051
1243
|
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1244
|
+
const isSyncComplete = interval[1] === hexToNumber(last.number);
|
|
1245
|
+
const {
|
|
1246
|
+
intervals: requiredIntervals,
|
|
1247
|
+
factoryIntervals: requiredFactoryIntervals,
|
|
1248
|
+
} = getRequiredIntervalsWithFilters({
|
|
1249
|
+
interval,
|
|
1250
|
+
filters: params.eventCallbacks.map(({ filter }) => filter),
|
|
1251
|
+
cachedIntervals: params.cachedIntervals,
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
let closestToTipBlock: SyncBlock | undefined;
|
|
1255
|
+
if (requiredIntervals.length > 0 || requiredFactoryIntervals.length > 0) {
|
|
1256
|
+
const pwr = promiseWithResolvers<void>();
|
|
1257
|
+
|
|
1258
|
+
const durationTimer = setTimeout(
|
|
1259
|
+
() => {
|
|
1260
|
+
params.common.logger.warn({
|
|
1261
|
+
msg: "Fetching backfill JSON-RPC data is taking longer than expected",
|
|
1262
|
+
chain: params.chain.name,
|
|
1263
|
+
chain_id: params.chain.id,
|
|
1264
|
+
block_range: JSON.stringify(interval),
|
|
1265
|
+
duration: endClock(),
|
|
1266
|
+
});
|
|
1267
|
+
},
|
|
1268
|
+
params.common.options.command === "dev" ? 10_000 : 50_000,
|
|
1269
|
+
);
|
|
1270
|
+
|
|
1271
|
+
closestToTipBlock = await params.database.syncQB
|
|
1272
|
+
.transaction(async (tx) => {
|
|
1273
|
+
const syncStore = createSyncStore({ common: params.common, qb: tx });
|
|
1274
|
+
const logs = await historicalSync.syncBlockRangeData({
|
|
1275
|
+
interval,
|
|
1276
|
+
requiredIntervals,
|
|
1277
|
+
requiredFactoryIntervals,
|
|
1278
|
+
syncStore,
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
// Wait for the previous interval to complete `syncBlockData`.
|
|
1282
|
+
await promise;
|
|
1283
|
+
|
|
1284
|
+
if (isSyncComplete === false) {
|
|
1285
|
+
// Queue the next interval
|
|
1286
|
+
intervalCallback({
|
|
1287
|
+
interval: [
|
|
1288
|
+
Math.min(interval[1] + 1, hexToNumber(last.number)),
|
|
1289
|
+
Math.min(
|
|
1290
|
+
interval[1] + 1 + estimateRange,
|
|
1291
|
+
hexToNumber(last.number),
|
|
1292
|
+
),
|
|
1293
|
+
],
|
|
1294
|
+
promise: pwr.promise,
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
const closestToTipBlock = await historicalSync.syncBlockData({
|
|
1299
|
+
interval,
|
|
1300
|
+
requiredIntervals,
|
|
1301
|
+
logs,
|
|
1302
|
+
syncStore,
|
|
1303
|
+
});
|
|
1304
|
+
if (params.chain.disableCache === false) {
|
|
1305
|
+
await syncStore.insertIntervals({
|
|
1306
|
+
intervals: requiredIntervals,
|
|
1307
|
+
factoryIntervals: requiredFactoryIntervals,
|
|
1308
|
+
chainId: params.chain.id,
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
return closestToTipBlock;
|
|
1313
|
+
})
|
|
1314
|
+
.catch((error) => {
|
|
1315
|
+
if (error instanceof ShutdownError) {
|
|
1316
|
+
throw error;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
params.common.logger.warn({
|
|
1320
|
+
msg: "Failed to fetch backfill JSON-RPC data",
|
|
1321
|
+
chain: params.chain.name,
|
|
1322
|
+
chain_id: params.chain.id,
|
|
1323
|
+
block_range: JSON.stringify(interval),
|
|
1324
|
+
duration: endClock(),
|
|
1325
|
+
error,
|
|
1326
|
+
});
|
|
1327
|
+
throw error;
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
clearTimeout(durationTimer);
|
|
1331
|
+
|
|
1332
|
+
const duration = endClock();
|
|
1333
|
+
|
|
1334
|
+
// Use the duration and interval of the last call to `sync` to update estimate
|
|
1335
|
+
estimateRange = estimate({
|
|
1336
|
+
from: interval[0],
|
|
1337
|
+
to: interval[1],
|
|
1338
|
+
target: params.common.options.command === "dev" ? 2_000 : 10_000,
|
|
1339
|
+
result: duration,
|
|
1340
|
+
min: 25,
|
|
1341
|
+
max: 100_000,
|
|
1342
|
+
prev: estimateRange,
|
|
1343
|
+
maxIncrease: 1.5,
|
|
1059
1344
|
});
|
|
1060
|
-
}, 5_000);
|
|
1061
|
-
|
|
1062
|
-
let synced: SyncBlock | undefined;
|
|
1063
|
-
try {
|
|
1064
|
-
synced = await historicalSync.sync(interval);
|
|
1065
|
-
} catch (error) {
|
|
1066
|
-
if (error instanceof ShutdownError) {
|
|
1067
|
-
throw error;
|
|
1068
|
-
}
|
|
1069
1345
|
|
|
1070
|
-
params.common.logger.
|
|
1071
|
-
msg: "
|
|
1346
|
+
params.common.logger.trace({
|
|
1347
|
+
msg: "Updated block range estimate for fetching backfill JSON-RPC data",
|
|
1072
1348
|
chain: params.chain.name,
|
|
1073
1349
|
chain_id: params.chain.id,
|
|
1074
|
-
|
|
1075
|
-
duration: endClock(),
|
|
1076
|
-
error,
|
|
1350
|
+
range: estimateRange,
|
|
1077
1351
|
});
|
|
1078
|
-
throw error;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
clearTimeout(durationTimer);
|
|
1082
|
-
|
|
1083
|
-
// Update cursor to record progress
|
|
1084
|
-
cursor = interval[1] + 1;
|
|
1085
1352
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
if (synced === undefined) {
|
|
1089
|
-
// If the all known blocks are synced, then update `syncProgress.current`, else
|
|
1090
|
-
// progress to the next iteration.
|
|
1091
|
-
if (interval[1] === hexToNumber(last.number)) {
|
|
1092
|
-
params.syncProgress.current = last;
|
|
1093
|
-
} else {
|
|
1094
|
-
continue;
|
|
1095
|
-
}
|
|
1353
|
+
// Resolve promise so the next interval can continue.
|
|
1354
|
+
pwr.resolve();
|
|
1096
1355
|
} else {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1356
|
+
// Wait for the previous interval to complete `syncBlockData`.
|
|
1357
|
+
await promise;
|
|
1358
|
+
|
|
1359
|
+
if (isSyncComplete === false) {
|
|
1360
|
+
// Queue the next interval
|
|
1361
|
+
intervalCallback({
|
|
1362
|
+
interval: [
|
|
1363
|
+
Math.min(interval[1] + 1, hexToNumber(last.number)),
|
|
1364
|
+
Math.min(interval[1] + 1 + estimateRange, hexToNumber(last.number)),
|
|
1365
|
+
],
|
|
1366
|
+
promise: Promise.resolve(),
|
|
1367
|
+
});
|
|
1101
1368
|
}
|
|
1369
|
+
}
|
|
1102
1370
|
|
|
1103
|
-
|
|
1371
|
+
if (interval[1] === hexToNumber(last.number)) {
|
|
1372
|
+
params.syncProgress.current = last;
|
|
1373
|
+
}
|
|
1104
1374
|
|
|
1375
|
+
if (closestToTipBlock) {
|
|
1105
1376
|
params.common.metrics.ponder_sync_block.set(
|
|
1106
1377
|
label,
|
|
1107
|
-
hexToNumber(
|
|
1378
|
+
hexToNumber(closestToTipBlock.number),
|
|
1108
1379
|
);
|
|
1109
1380
|
params.common.metrics.ponder_sync_block_timestamp.set(
|
|
1110
1381
|
label,
|
|
1111
|
-
hexToNumber(
|
|
1112
|
-
);
|
|
1113
|
-
params.common.metrics.ponder_historical_completed_blocks.inc(
|
|
1114
|
-
label,
|
|
1115
|
-
interval[1] - interval[0] + 1,
|
|
1382
|
+
hexToNumber(closestToTipBlock.timestamp),
|
|
1116
1383
|
);
|
|
1384
|
+
} else {
|
|
1385
|
+
params.common.metrics.ponder_sync_block.set(label, interval[1]);
|
|
1386
|
+
}
|
|
1117
1387
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
25,
|
|
1123
|
-
Math.round((1_000 * (interval[1] - interval[0])) / duration),
|
|
1124
|
-
),
|
|
1125
|
-
estimateRange * 2,
|
|
1126
|
-
100_000,
|
|
1127
|
-
);
|
|
1388
|
+
params.common.metrics.ponder_historical_completed_blocks.inc(
|
|
1389
|
+
label,
|
|
1390
|
+
interval[1] - interval[0] + 1,
|
|
1391
|
+
);
|
|
1128
1392
|
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
chain: params.chain.name,
|
|
1132
|
-
chain_id: params.chain.id,
|
|
1133
|
-
range: estimateRange,
|
|
1134
|
-
});
|
|
1135
|
-
}
|
|
1393
|
+
return requiredIntervals.length > 0;
|
|
1394
|
+
}
|
|
1136
1395
|
|
|
1137
|
-
|
|
1396
|
+
const { callback, generator } =
|
|
1397
|
+
createCallbackGenerator<IteratorResult<number>>();
|
|
1398
|
+
|
|
1399
|
+
(async () => {
|
|
1400
|
+
for await (const { interval, promise } of intervalGenerator) {
|
|
1401
|
+
// Note: this relies on the invariant that `syncInterval`
|
|
1402
|
+
// will always resolve promises in the order it was called.
|
|
1403
|
+
syncInterval({ interval, promise }).then((didInsertData) => {
|
|
1404
|
+
const isDone = interval[1] === hexToNumber(last.number);
|
|
1405
|
+
if (didInsertData || isDone) {
|
|
1406
|
+
callback({ value: interval[1], done: false });
|
|
1407
|
+
}
|
|
1138
1408
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
chain: params.chain.name,
|
|
1143
|
-
chain_id: params.chain.id,
|
|
1144
|
-
duration: backfillEndClock(),
|
|
1409
|
+
if (isDone) {
|
|
1410
|
+
callback({ value: undefined, done: true });
|
|
1411
|
+
}
|
|
1145
1412
|
});
|
|
1146
|
-
return;
|
|
1147
1413
|
}
|
|
1414
|
+
})();
|
|
1415
|
+
|
|
1416
|
+
for await (const result of generator) {
|
|
1417
|
+
if (result.done) break;
|
|
1418
|
+
yield result.value;
|
|
1148
1419
|
}
|
|
1420
|
+
|
|
1421
|
+
params.common.logger.info({
|
|
1422
|
+
msg: "Finished fetching backfill JSON-RPC data",
|
|
1423
|
+
chain: params.chain.name,
|
|
1424
|
+
chain_id: params.chain.id,
|
|
1425
|
+
duration: backfillEndClock(),
|
|
1426
|
+
});
|
|
1149
1427
|
}
|
|
1150
1428
|
|
|
1151
1429
|
/**
|
|
@@ -1202,7 +1480,7 @@ export async function* mergeAsyncGeneratorsWithEventOrder(
|
|
|
1202
1480
|
|
|
1203
1481
|
mergedResults.push({
|
|
1204
1482
|
events: left,
|
|
1205
|
-
chainId: event.
|
|
1483
|
+
chainId: event.chain.id,
|
|
1206
1484
|
checkpoint:
|
|
1207
1485
|
right.length > 0 ? event.checkpoint : result.value.checkpoint,
|
|
1208
1486
|
blockRange,
|