ponder 0.11.21 → 0.11.22

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/esm/bin/commands/createViews.js +9 -20
  3. package/dist/esm/bin/commands/createViews.js.map +1 -1
  4. package/dist/esm/bin/commands/dev.js +1 -1
  5. package/dist/esm/bin/commands/dev.js.map +1 -1
  6. package/dist/esm/bin/commands/list.js +4 -7
  7. package/dist/esm/bin/commands/list.js.map +1 -1
  8. package/dist/esm/bin/commands/prune.js +9 -21
  9. package/dist/esm/bin/commands/prune.js.map +1 -1
  10. package/dist/esm/bin/commands/serve.js +1 -1
  11. package/dist/esm/bin/commands/serve.js.map +1 -1
  12. package/dist/esm/bin/commands/start.js +3 -3
  13. package/dist/esm/bin/commands/start.js.map +1 -1
  14. package/dist/esm/bin/utils/run.js +159 -180
  15. package/dist/esm/bin/utils/run.js.map +1 -1
  16. package/dist/esm/build/index.js +1 -48
  17. package/dist/esm/build/index.js.map +1 -1
  18. package/dist/esm/build/plugin.js +1 -1
  19. package/dist/esm/client/index.js +9 -13
  20. package/dist/esm/client/index.js.map +1 -1
  21. package/dist/esm/database/index.js +429 -141
  22. package/dist/esm/database/index.js.map +1 -1
  23. package/dist/esm/drizzle/index.js.map +1 -1
  24. package/dist/esm/drizzle/kit/index.js.map +1 -1
  25. package/dist/esm/drizzle/onchain.js +1 -8
  26. package/dist/esm/drizzle/onchain.js.map +1 -1
  27. package/dist/esm/graphql/index.js +16 -19
  28. package/dist/esm/graphql/index.js.map +1 -1
  29. package/dist/esm/graphql/middleware.js +7 -3
  30. package/dist/esm/graphql/middleware.js.map +1 -1
  31. package/dist/esm/indexing-store/cache.js +32 -26
  32. package/dist/esm/indexing-store/cache.js.map +1 -1
  33. package/dist/esm/indexing-store/historical.js +32 -23
  34. package/dist/esm/indexing-store/historical.js.map +1 -1
  35. package/dist/esm/indexing-store/index.js +18 -1
  36. package/dist/esm/indexing-store/index.js.map +1 -1
  37. package/dist/esm/indexing-store/realtime.js +140 -89
  38. package/dist/esm/indexing-store/realtime.js.map +1 -1
  39. package/dist/esm/internal/errors.js +0 -12
  40. package/dist/esm/internal/errors.js.map +1 -1
  41. package/dist/esm/server/index.js +2 -10
  42. package/dist/esm/server/index.js.map +1 -1
  43. package/dist/esm/sync-store/index.js +432 -403
  44. package/dist/esm/sync-store/index.js.map +1 -1
  45. package/dist/esm/utils/wait.js +0 -2
  46. package/dist/esm/utils/wait.js.map +1 -1
  47. package/dist/types/bin/commands/createViews.d.ts.map +1 -1
  48. package/dist/types/bin/commands/list.d.ts.map +1 -1
  49. package/dist/types/bin/commands/prune.d.ts.map +1 -1
  50. package/dist/types/bin/commands/start.d.ts +0 -2
  51. package/dist/types/bin/commands/start.d.ts.map +1 -1
  52. package/dist/types/bin/utils/run.d.ts +1 -1
  53. package/dist/types/bin/utils/run.d.ts.map +1 -1
  54. package/dist/types/build/index.d.ts +1 -1
  55. package/dist/types/build/index.d.ts.map +1 -1
  56. package/dist/types/client/index.d.ts.map +1 -1
  57. package/dist/types/database/index.d.ts +73 -25
  58. package/dist/types/database/index.d.ts.map +1 -1
  59. package/dist/types/drizzle/index.d.ts +3 -2
  60. package/dist/types/drizzle/index.d.ts.map +1 -1
  61. package/dist/types/drizzle/kit/index.d.ts +4 -3
  62. package/dist/types/drizzle/kit/index.d.ts.map +1 -1
  63. package/dist/types/drizzle/onchain.d.ts +5 -12
  64. package/dist/types/drizzle/onchain.d.ts.map +1 -1
  65. package/dist/types/graphql/index.d.ts +4 -2
  66. package/dist/types/graphql/index.d.ts.map +1 -1
  67. package/dist/types/graphql/middleware.d.ts +1 -1
  68. package/dist/types/graphql/middleware.d.ts.map +1 -1
  69. package/dist/types/indexing-store/cache.d.ts +12 -5
  70. package/dist/types/indexing-store/cache.d.ts.map +1 -1
  71. package/dist/types/indexing-store/historical.d.ts +7 -2
  72. package/dist/types/indexing-store/historical.d.ts.map +1 -1
  73. package/dist/types/indexing-store/index.d.ts +2 -4
  74. package/dist/types/indexing-store/index.d.ts.map +1 -1
  75. package/dist/types/indexing-store/realtime.d.ts +3 -1
  76. package/dist/types/indexing-store/realtime.d.ts.map +1 -1
  77. package/dist/types/internal/errors.d.ts +0 -4
  78. package/dist/types/internal/errors.d.ts.map +1 -1
  79. package/dist/types/server/index.d.ts +1 -1
  80. package/dist/types/server/index.d.ts.map +1 -1
  81. package/dist/types/sync/index.d.ts +1 -1
  82. package/dist/types/sync-store/index.d.ts.map +1 -1
  83. package/dist/types/utils/wait.d.ts.map +1 -1
  84. package/package.json +2 -2
  85. package/src/bin/commands/createViews.ts +26 -37
  86. package/src/bin/commands/dev.ts +1 -1
  87. package/src/bin/commands/list.ts +4 -7
  88. package/src/bin/commands/prune.ts +17 -31
  89. package/src/bin/commands/serve.ts +1 -1
  90. package/src/bin/commands/start.ts +3 -4
  91. package/src/bin/utils/run.ts +210 -256
  92. package/src/build/index.ts +2 -53
  93. package/src/build/plugin.ts +1 -1
  94. package/src/client/index.ts +10 -21
  95. package/src/database/index.ts +742 -331
  96. package/src/drizzle/index.ts +3 -2
  97. package/src/drizzle/kit/index.ts +5 -2
  98. package/src/drizzle/onchain.ts +2 -26
  99. package/src/graphql/index.ts +26 -31
  100. package/src/graphql/middleware.ts +7 -5
  101. package/src/indexing-store/cache.ts +52 -35
  102. package/src/indexing-store/historical.ts +40 -28
  103. package/src/indexing-store/index.ts +27 -2
  104. package/src/indexing-store/realtime.ts +220 -176
  105. package/src/internal/errors.ts +0 -9
  106. package/src/server/index.ts +3 -14
  107. package/src/sync-store/index.ts +997 -870
  108. package/src/utils/wait.ts +0 -1
  109. package/dist/esm/database/queryBuilder.js +0 -206
  110. package/dist/esm/database/queryBuilder.js.map +0 -1
  111. package/dist/esm/database/utils.js +0 -100
  112. package/dist/esm/database/utils.js.map +0 -1
  113. package/dist/esm/drizzle/json.js +0 -119
  114. package/dist/esm/drizzle/json.js.map +0 -1
  115. package/dist/types/database/queryBuilder.d.ts +0 -37
  116. package/dist/types/database/queryBuilder.d.ts.map +0 -1
  117. package/dist/types/database/utils.d.ts +0 -25
  118. package/dist/types/database/utils.d.ts.map +0 -1
  119. package/dist/types/drizzle/json.d.ts +0 -51
  120. package/dist/types/drizzle/json.d.ts.map +0 -1
  121. package/src/database/queryBuilder.ts +0 -319
  122. package/src/database/utils.ts +0 -140
  123. package/src/drizzle/json.ts +0 -154
@@ -1,17 +1,5 @@
1
1
  import { runCodegen } from "@/bin/utils/codegen.js";
2
- import {
3
- type Database,
4
- getPonderCheckpointTable,
5
- getPonderMetaTable,
6
- } from "@/database/index.js";
7
- import {
8
- commitBlock,
9
- createIndexes,
10
- createTrigger,
11
- dropTrigger,
12
- finalize,
13
- revert,
14
- } from "@/database/utils.js";
2
+ import type { Database } from "@/database/index.js";
15
3
  import { createIndexingCache } from "@/indexing-store/cache.js";
16
4
  import { createHistoricalIndexingStore } from "@/indexing-store/historical.js";
17
5
  import { createRealtimeIndexingStore } from "@/indexing-store/realtime.js";
@@ -36,8 +24,9 @@ import { recordAsyncGenerator } from "@/utils/generators.js";
36
24
  import { mutex } from "@/utils/mutex.js";
37
25
  import { never } from "@/utils/never.js";
38
26
  import { startClock } from "@/utils/timer.js";
39
- import { getTableName, is, sql } from "drizzle-orm";
27
+ import { type TableConfig, getTableName, is, sql } from "drizzle-orm";
40
28
  import { PgTable } from "drizzle-orm/pg-core";
29
+ import type { PgTableWithColumns } from "drizzle-orm/pg-core";
41
30
 
42
31
  /** Starts the sync and indexing services for the specified build. */
43
32
  export async function run({
@@ -61,12 +50,6 @@ export async function run({
61
50
  onFatalError: (error: Error) => void;
62
51
  onReloadableError: (error: Error) => void;
63
52
  }) {
64
- const PONDER_META = getPonderMetaTable(namespaceBuild.schema);
65
- const PONDER_CHECKPOINT = getPonderCheckpointTable(namespaceBuild.schema);
66
- const tables = Object.values(schemaBuild.schema).filter(
67
- (table): table is PgTable => is(table, PgTable),
68
- );
69
-
70
53
  await database.migrateSync();
71
54
 
72
55
  runCodegen({ common });
@@ -111,12 +94,6 @@ export async function run({
111
94
  eventCount,
112
95
  });
113
96
 
114
- const historicalIndexingStore = createHistoricalIndexingStore({
115
- common,
116
- schemaBuild,
117
- indexingCache,
118
- });
119
-
120
97
  for (const chain of indexingBuild.chains) {
121
98
  const label = { chain: chain.name };
122
99
  common.metrics.ponder_historical_total_indexing_seconds.set(
@@ -152,50 +129,47 @@ export async function run({
152
129
 
153
130
  // If the initial checkpoint is zero, we need to run setup events.
154
131
  if (crashRecoveryCheckpoint === undefined) {
155
- await database.userQB().transaction(async (tx) => {
156
- historicalIndexingStore.qb = tx;
157
- indexingCache.qb = tx;
158
-
159
- const result = await indexing.processSetupEvents({
160
- db: historicalIndexingStore,
161
- });
162
-
163
- if (result.status === "error") {
164
- onReloadableError(result.error);
165
- return;
166
- }
132
+ await database.retry(async () => {
133
+ await database.transaction(async (client, tx) => {
134
+ const historicalIndexingStore = createHistoricalIndexingStore({
135
+ common,
136
+ schemaBuild,
137
+ indexingCache,
138
+ db: tx,
139
+ client,
140
+ });
141
+ const result = await indexing.processSetupEvents({
142
+ db: historicalIndexingStore,
143
+ });
167
144
 
168
- try {
169
- await indexingCache.flush();
170
- } catch (error) {
171
- if (error instanceof FlushError) {
172
- onReloadableError(error as Error);
145
+ if (result.status === "error") {
146
+ onReloadableError(result.error);
173
147
  return;
174
148
  }
175
- throw error;
176
- }
149
+
150
+ try {
151
+ await indexingCache.flush({ client });
152
+ } catch (error) {
153
+ if (error instanceof FlushError) {
154
+ onReloadableError(error as Error);
155
+ return;
156
+ }
157
+ throw error;
158
+ }
159
+ });
177
160
  });
178
161
  }
179
162
 
180
163
  // Note: `_ponder_checkpoint` must be updated after the setup events are processed.
181
- await database
182
- .adminQB("update_checkpoints")
183
- .insert(PONDER_CHECKPOINT)
184
- .values(
185
- indexingBuild.chains.map((chain) => ({
186
- chainName: chain.name,
187
- chainId: chain.id,
188
- latestCheckpoint: sync.getStartCheckpoint(chain),
189
- safeCheckpoint: sync.getStartCheckpoint(chain),
190
- })),
191
- )
192
- .onConflictDoUpdate({
193
- target: PONDER_CHECKPOINT.chainName,
194
- set: {
195
- safeCheckpoint: sql`excluded.safe_checkpoint`,
196
- latestCheckpoint: sql`excluded.latest_checkpoint`,
197
- },
198
- });
164
+ await database.setCheckpoints({
165
+ checkpoints: indexingBuild.chains.map((chain) => ({
166
+ chainName: chain.name,
167
+ chainId: chain.id,
168
+ latestCheckpoint: sync.getStartCheckpoint(chain),
169
+ safeCheckpoint: sync.getStartCheckpoint(chain),
170
+ })),
171
+ db: database.qb.drizzle,
172
+ });
199
173
 
200
174
  // Run historical indexing until complete.
201
175
  for await (const events of recordAsyncGenerator(
@@ -213,10 +187,14 @@ export async function run({
213
187
  )) {
214
188
  let endClock = startClock();
215
189
 
216
- indexingCache.qb = database.userQB;
217
190
  await Promise.all([
218
- indexingCache.prefetch({ events: events.events }),
219
- cachedViemClient.prefetch({ events: events.events }),
191
+ indexingCache.prefetch({
192
+ events: events.events,
193
+ db: database.qb.drizzle,
194
+ }),
195
+ cachedViemClient.prefetch({
196
+ events: events.events,
197
+ }),
220
198
  ]);
221
199
  common.metrics.ponder_historical_transform_duration.inc(
222
200
  { step: "prefetch" },
@@ -224,167 +202,161 @@ export async function run({
224
202
  );
225
203
  if (events.events.length > 0) {
226
204
  endClock = startClock();
205
+ await database.retry(async () => {
206
+ await database
207
+ .transaction(async (client, tx) => {
208
+ common.metrics.ponder_historical_transform_duration.inc(
209
+ { step: "begin" },
210
+ endClock(),
211
+ );
227
212
 
228
- await database
229
- .userQB()
230
- .transaction(async (tx) => {
231
- historicalIndexingStore.qb = tx;
232
- indexingCache.qb = tx;
233
-
234
- common.metrics.ponder_historical_transform_duration.inc(
235
- { step: "begin" },
236
- endClock(),
237
- );
238
-
239
- endClock = startClock();
240
-
241
- const eventChunks = chunk(events.events, 93);
242
- for (const eventChunk of eventChunks) {
243
- const result = await indexing.processEvents({
244
- events: eventChunk,
245
- db: historicalIndexingStore,
246
- cache: indexingCache,
213
+ endClock = startClock();
214
+ const historicalIndexingStore = createHistoricalIndexingStore({
215
+ common,
216
+ schemaBuild,
217
+ indexingCache,
218
+ db: tx,
219
+ client,
247
220
  });
248
221
 
249
- if (result.status === "error") {
250
- onReloadableError(result.error);
251
- return;
252
- }
222
+ const eventChunks = chunk(events.events, 93);
223
+ for (const eventChunk of eventChunks) {
224
+ const result = await indexing.processEvents({
225
+ events: eventChunk,
226
+ db: historicalIndexingStore,
227
+ cache: indexingCache,
228
+ });
253
229
 
254
- const checkpoint = decodeCheckpoint(
255
- eventChunk[eventChunk.length - 1]!.checkpoint,
256
- );
230
+ if (result.status === "error") {
231
+ onReloadableError(result.error);
232
+ return;
233
+ }
257
234
 
258
- if (preBuild.ordering === "multichain") {
259
- const chain = indexingBuild.chains.find(
260
- (chain) => chain.id === Number(checkpoint.chainId),
261
- )!;
262
- common.metrics.ponder_historical_completed_indexing_seconds.set(
263
- { chain: chain.name },
264
- Math.max(
265
- Number(checkpoint.blockTimestamp) -
266
- Math.max(
267
- sync.seconds[chain.name]!.cached,
268
- sync.seconds[chain.name]!.start,
269
- ),
270
- 0,
271
- ),
235
+ const checkpoint = decodeCheckpoint(
236
+ eventChunk[eventChunk.length - 1]!.checkpoint,
272
237
  );
273
- common.metrics.ponder_indexing_timestamp.set(
274
- { chain: chain.name },
275
- Number(checkpoint.blockTimestamp),
276
- );
277
- } else {
278
- for (const chain of indexingBuild.chains) {
238
+
239
+ if (preBuild.ordering === "multichain") {
240
+ const chain = indexingBuild.chains.find(
241
+ (chain) => chain.id === Number(checkpoint.chainId),
242
+ )!;
279
243
  common.metrics.ponder_historical_completed_indexing_seconds.set(
280
244
  { chain: chain.name },
281
- Math.min(
282
- Math.max(
283
- Number(checkpoint.blockTimestamp) -
284
- Math.max(
285
- sync.seconds[chain.name]!.cached,
286
- sync.seconds[chain.name]!.start,
287
- ),
288
- 0,
289
- ),
290
- Math.max(
291
- sync.seconds[chain.name]!.end -
245
+ Math.max(
246
+ Number(checkpoint.blockTimestamp) -
247
+ Math.max(
248
+ sync.seconds[chain.name]!.cached,
292
249
  sync.seconds[chain.name]!.start,
293
- 0,
294
- ),
250
+ ),
251
+ 0,
295
252
  ),
296
253
  );
297
254
  common.metrics.ponder_indexing_timestamp.set(
298
255
  { chain: chain.name },
299
- Math.max(
300
- Number(checkpoint.blockTimestamp),
301
- sync.seconds[chain.name]!.end,
302
- ),
256
+ Number(checkpoint.blockTimestamp),
303
257
  );
258
+ } else {
259
+ for (const chain of indexingBuild.chains) {
260
+ common.metrics.ponder_historical_completed_indexing_seconds.set(
261
+ { chain: chain.name },
262
+ Math.min(
263
+ Math.max(
264
+ Number(checkpoint.blockTimestamp) -
265
+ Math.max(
266
+ sync.seconds[chain.name]!.cached,
267
+ sync.seconds[chain.name]!.start,
268
+ ),
269
+ 0,
270
+ ),
271
+ Math.max(
272
+ sync.seconds[chain.name]!.end -
273
+ sync.seconds[chain.name]!.start,
274
+ 0,
275
+ ),
276
+ ),
277
+ );
278
+ common.metrics.ponder_indexing_timestamp.set(
279
+ { chain: chain.name },
280
+ Math.max(
281
+ Number(checkpoint.blockTimestamp),
282
+ sync.seconds[chain.name]!.end,
283
+ ),
284
+ );
285
+ }
304
286
  }
305
- }
306
287
 
307
- // Note: allows for terminal and logs to be updated
308
- if (preBuild.databaseConfig.kind === "pglite") {
309
- await new Promise(setImmediate);
288
+ // Note: allows for terminal and logs to be updated
289
+ if (preBuild.databaseConfig.kind === "pglite") {
290
+ await new Promise(setImmediate);
291
+ }
292
+ }
293
+ await new Promise(setImmediate);
294
+
295
+ // underlying metrics collection is actually synchronous
296
+ // https://github.com/siimon/prom-client/blob/master/lib/histogram.js#L102-L125
297
+ const { eta, progress } = await getAppProgress(common.metrics);
298
+ if (eta === undefined || progress === undefined) {
299
+ common.logger.info({
300
+ service: "app",
301
+ msg: `Indexed ${events.events.length} events`,
302
+ });
303
+ } else {
304
+ common.logger.info({
305
+ service: "app",
306
+ msg: `Indexed ${events.events.length} events with ${formatPercentage(progress)} complete and ${formatEta(eta * 1_000)} remaining`,
307
+ });
310
308
  }
311
- }
312
- await new Promise(setImmediate);
313
309
 
314
- // underlying metrics collection is actually synchronous
315
- // https://github.com/siimon/prom-client/blob/master/lib/histogram.js#L102-L125
316
- const { eta, progress } = await getAppProgress(common.metrics);
317
- if (eta === undefined || progress === undefined) {
318
- common.logger.info({
319
- service: "app",
320
- msg: `Indexed ${events.events.length} events`,
321
- });
322
- } else {
323
- common.logger.info({
324
- service: "app",
325
- msg: `Indexed ${events.events.length} events with ${formatPercentage(progress)} complete and ${formatEta(eta * 1_000)} remaining`,
326
- });
327
- }
310
+ common.metrics.ponder_historical_transform_duration.inc(
311
+ { step: "index" },
312
+ endClock(),
313
+ );
314
+
315
+ endClock = startClock();
316
+ // Note: at this point, the next events can be preloaded, as long as the are not indexed until
317
+ // the "flush" + "finalize" is complete.
328
318
 
329
- common.metrics.ponder_historical_transform_duration.inc(
330
- { step: "index" },
331
- endClock(),
332
- );
333
-
334
- endClock = startClock();
335
- // Note: at this point, the next events can be preloaded, as long as the are not indexed until
336
- // the "flush" + "finalize" is complete.
337
-
338
- try {
339
- await indexingCache.flush();
340
- } catch (error) {
341
- if (error instanceof FlushError) {
342
- onReloadableError(error as Error);
343
- return;
319
+ try {
320
+ await indexingCache.flush({ client });
321
+ } catch (error) {
322
+ if (error instanceof FlushError) {
323
+ onReloadableError(error as Error);
324
+ return;
325
+ }
326
+ throw error;
344
327
  }
345
- throw error;
346
- }
347
328
 
348
- common.metrics.ponder_historical_transform_duration.inc(
349
- { step: "load" },
350
- endClock(),
351
- );
352
- endClock = startClock();
353
-
354
- if (events.checkpoints.length > 0) {
355
- await database
356
- .adminQB("update_checkpoints")
357
- .insert(PONDER_CHECKPOINT)
358
- .values(
359
- events.checkpoints.map(({ chainId, checkpoint }) => ({
329
+ common.metrics.ponder_historical_transform_duration.inc(
330
+ { step: "load" },
331
+ endClock(),
332
+ );
333
+ endClock = startClock();
334
+
335
+ await database.setCheckpoints({
336
+ checkpoints: events.checkpoints.map(
337
+ ({ chainId, checkpoint }) => ({
360
338
  chainName: indexingBuild.chains.find(
361
339
  (chain) => chain.id === chainId,
362
340
  )!.name,
363
341
  chainId,
364
342
  latestCheckpoint: checkpoint,
365
343
  safeCheckpoint: checkpoint,
366
- })),
367
- )
368
- .onConflictDoUpdate({
369
- target: PONDER_CHECKPOINT.chainName,
370
- set: {
371
- safeCheckpoint: sql`excluded.safe_checkpoint`,
372
- latestCheckpoint: sql`excluded.latest_checkpoint`,
373
- },
374
- });
375
- }
376
-
377
- common.metrics.ponder_historical_transform_duration.inc(
378
- { step: "finalize" },
379
- endClock(),
380
- );
381
- endClock = startClock();
382
- })
383
- .catch((error) => {
384
- indexingCache.rollback();
385
- throw error;
386
- });
344
+ }),
345
+ ),
346
+ db: tx,
347
+ });
387
348
 
349
+ common.metrics.ponder_historical_transform_duration.inc(
350
+ { step: "finalize" },
351
+ endClock(),
352
+ );
353
+ endClock = startClock();
354
+ })
355
+ .catch((error) => {
356
+ indexingCache.rollback();
357
+ throw error;
358
+ });
359
+ });
388
360
  cachedViemClient.clear();
389
361
  common.metrics.ponder_historical_transform_duration.inc(
390
362
  { step: "commit" },
@@ -428,26 +400,28 @@ export async function run({
428
400
  msg: "Completed historical indexing",
429
401
  });
430
402
 
431
- await createIndexes(database.adminQB, { statements: schemaBuild.statements });
432
- await Promise.all(
433
- tables.map((table) => createTrigger(database.adminQB, { table })),
434
- );
403
+ await database.createIndexes();
404
+ await database.createTriggers();
435
405
 
436
406
  if (namespaceBuild.viewsSchema) {
437
- await database.adminQB("create_views").transaction(async (tx) => {
438
- await tx().execute(
407
+ await database.wrap({ method: "create-views" }, async () => {
408
+ await database.qb.drizzle.execute(
439
409
  sql.raw(`CREATE SCHEMA IF NOT EXISTS "${namespaceBuild.viewsSchema}"`),
440
410
  );
441
411
 
412
+ const tables = Object.values(schemaBuild.schema).filter(
413
+ (table): table is PgTableWithColumns<TableConfig> => is(table, PgTable),
414
+ );
415
+
442
416
  for (const table of tables) {
443
417
  // Note: drop views before creating new ones to avoid enum errors.
444
- await tx().execute(
418
+ await database.qb.drizzle.execute(
445
419
  sql.raw(
446
420
  `DROP VIEW IF EXISTS "${namespaceBuild.viewsSchema}"."${getTableName(table)}"`,
447
421
  ),
448
422
  );
449
423
 
450
- await tx().execute(
424
+ await database.qb.drizzle.execute(
451
425
  sql.raw(
452
426
  `CREATE VIEW "${namespaceBuild.viewsSchema}"."${getTableName(table)}" AS SELECT * FROM "${namespaceBuild.schema}"."${getTableName(table)}"`,
453
427
  ),
@@ -459,13 +433,13 @@ export async function run({
459
433
  msg: `Created ${tables.length} views in schema "${namespaceBuild.viewsSchema}"`,
460
434
  });
461
435
 
462
- await tx().execute(
436
+ await database.qb.drizzle.execute(
463
437
  sql.raw(
464
438
  `CREATE OR REPLACE VIEW "${namespaceBuild.viewsSchema}"."_ponder_meta" AS SELECT * FROM "${namespaceBuild.schema}"."_ponder_meta"`,
465
439
  ),
466
440
  );
467
441
 
468
- await tx().execute(
442
+ await database.qb.drizzle.execute(
469
443
  sql.raw(
470
444
  `CREATE OR REPLACE VIEW "${namespaceBuild.viewsSchema}"."_ponder_checkpoint" AS SELECT * FROM "${namespaceBuild.schema}"."_ponder_checkpoint"`,
471
445
  ),
@@ -475,7 +449,7 @@ export async function run({
475
449
  const notification = "status_notify()";
476
450
  const channel = `${namespaceBuild.viewsSchema}_status_channel`;
477
451
 
478
- await tx().execute(
452
+ await database.qb.drizzle.execute(
479
453
  sql.raw(`
480
454
  CREATE OR REPLACE FUNCTION "${namespaceBuild.viewsSchema}".${notification}
481
455
  RETURNS TRIGGER
@@ -488,7 +462,7 @@ export async function run({
488
462
  $$;`),
489
463
  );
490
464
 
491
- await tx().execute(
465
+ await database.qb.drizzle.execute(
492
466
  sql.raw(`
493
467
  CREATE OR REPLACE TRIGGER "${trigger}"
494
468
  AFTER INSERT OR UPDATE OR DELETE
@@ -499,16 +473,13 @@ export async function run({
499
473
  });
500
474
  }
501
475
 
502
- await database
503
- .adminQB("set_ready")
504
- .update(PONDER_META)
505
- .set({ value: sql`jsonb_set(value, '{is_ready}', to_jsonb(1))` });
476
+ await database.setReady();
506
477
 
507
478
  const realtimeIndexingStore = createRealtimeIndexingStore({
508
479
  common,
509
480
  schemaBuild,
481
+ database,
510
482
  });
511
- realtimeIndexingStore.qb = database.userQB;
512
483
 
513
484
  const onRealtimeEvent = mutex(async (event: RealtimeEvent) => {
514
485
  switch (event.type) {
@@ -542,11 +513,7 @@ export async function run({
542
513
 
543
514
  if (result.status === "error") onReloadableError(result.error);
544
515
 
545
- await Promise.all(
546
- tables.map((table) =>
547
- commitBlock(database.userQB, { table, checkpoint }),
548
- ),
549
- );
516
+ await database.commitBlock({ checkpoint, db: database.qb.drizzle });
550
517
 
551
518
  if (preBuild.ordering === "multichain") {
552
519
  common.metrics.ponder_indexing_timestamp.set(
@@ -564,10 +531,11 @@ export async function run({
564
531
  }
565
532
  }
566
533
 
567
- if (event.checkpoints.length > 0) {
568
- await database
569
- .adminQB("update_checkpoints")
570
- .insert(PONDER_CHECKPOINT)
534
+ await database.wrap({ method: "setCheckpoints" }, async () => {
535
+ if (event.checkpoints.length === 0) return;
536
+
537
+ await database.qb.drizzle
538
+ .insert(database.PONDER_CHECKPOINT)
571
539
  .values(
572
540
  event.checkpoints.map(({ chainId, checkpoint }) => ({
573
541
  chainName: indexingBuild.chains.find(
@@ -579,10 +547,12 @@ export async function run({
579
547
  })),
580
548
  )
581
549
  .onConflictDoUpdate({
582
- target: PONDER_CHECKPOINT.chainName,
583
- set: { latestCheckpoint: sql`excluded.latest_checkpoint` },
550
+ target: database.PONDER_CHECKPOINT.chainName,
551
+ set: {
552
+ latestCheckpoint: sql`excluded.latest_checkpoint`,
553
+ },
584
554
  });
585
- }
555
+ });
586
556
 
587
557
  break;
588
558
  }
@@ -590,41 +560,25 @@ export async function run({
590
560
  // Note: `_ponder_checkpoint` is not called here, instead it is called
591
561
  // in the `block` case.
592
562
 
593
- await database.userQB().transaction(async (tx) => {
594
- for (const table of tables) {
595
- await dropTrigger(tx, { table });
596
- const count = await revert(tx, {
597
- table,
598
- checkpoint: event.checkpoint,
599
- });
600
- common.logger.info({
601
- service: "database",
602
- msg: `Reverted ${count} unfinalized operations from '${getTableName(table)}'`,
603
- });
604
- await createTrigger(tx, { table });
605
- }
563
+ await database.removeTriggers();
564
+ await database.retry(async () => {
565
+ await database.qb.drizzle.transaction(async (tx) => {
566
+ await database.revert({ checkpoint: event.checkpoint, tx });
567
+ });
606
568
  });
569
+ await database.createTriggers();
607
570
 
608
571
  break;
609
572
 
610
573
  case "finalize":
611
- await database.userQB().transaction(async (tx) => {
612
- await tx("update_checkpoints").update(PONDER_CHECKPOINT).set({
613
- safeCheckpoint: event.checkpoint,
614
- });
615
-
616
- for (const table of tables) {
617
- await finalize(tx, { table, checkpoint: event.checkpoint });
618
-
619
- const decoded = decodeCheckpoint(event.checkpoint);
620
-
621
- common.logger.debug({
622
- service: "database",
623
- msg: `Updated finalized checkpoint to (timestamp=${decoded.blockTimestamp} chainId=${decoded.chainId} block=${decoded.blockNumber})`,
624
- });
625
- }
574
+ await database.qb.drizzle.update(database.PONDER_CHECKPOINT).set({
575
+ safeCheckpoint: event.checkpoint,
626
576
  });
627
577
 
578
+ await database.finalize({
579
+ checkpoint: event.checkpoint,
580
+ db: database.qb.drizzle,
581
+ });
628
582
  break;
629
583
 
630
584
  default: