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,12 +1,11 @@
|
|
|
1
1
|
import type { QB } from "@/database/queryBuilder.js";
|
|
2
|
-
import { getPrimaryKeyColumns } from "@/drizzle/index.js";
|
|
2
|
+
import { getPartitionName, getPrimaryKeyColumns } from "@/drizzle/index.js";
|
|
3
3
|
import { getColumnCasing } from "@/drizzle/kit/index.js";
|
|
4
4
|
import { addErrorMeta, toErrorMeta } from "@/indexing/index.js";
|
|
5
5
|
import type { Common } from "@/internal/common.js";
|
|
6
6
|
import {
|
|
7
7
|
CopyFlushError,
|
|
8
8
|
DelayedInsertError,
|
|
9
|
-
RetryableError,
|
|
10
9
|
ShutdownError,
|
|
11
10
|
} from "@/internal/errors.js";
|
|
12
11
|
import type {
|
|
@@ -16,6 +15,7 @@ import type {
|
|
|
16
15
|
} from "@/internal/types.js";
|
|
17
16
|
import { dedupe } from "@/utils/dedupe.js";
|
|
18
17
|
import { prettyPrint } from "@/utils/print.js";
|
|
18
|
+
import { promiseAllSettledWithThrow } from "@/utils/promiseAllSettledWithThrow.js";
|
|
19
19
|
import { startClock } from "@/utils/timer.js";
|
|
20
20
|
import {
|
|
21
21
|
type Table,
|
|
@@ -274,14 +274,12 @@ export const getCopyText = (table: Table, rows: Row[]) => {
|
|
|
274
274
|
return result;
|
|
275
275
|
};
|
|
276
276
|
|
|
277
|
-
export const getCopyHelper = (qb: QB) => {
|
|
277
|
+
export const getCopyHelper = (qb: QB, chainId?: number) => {
|
|
278
278
|
if (qb.$dialect === "pglite") {
|
|
279
279
|
return async (table: Table, text: string, includeSchema = true) => {
|
|
280
280
|
const target = includeSchema
|
|
281
|
-
? `"${getTableConfig(table).schema ?? "public"}"."${getTableName(
|
|
282
|
-
|
|
283
|
-
)}"`
|
|
284
|
-
: `"${getTableName(table)}"`;
|
|
281
|
+
? `"${getTableConfig(table).schema ?? "public"}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"`
|
|
282
|
+
: `"${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"`;
|
|
285
283
|
await qb.$client
|
|
286
284
|
.query(`COPY ${target} FROM '/dev/blob'`, [], {
|
|
287
285
|
blob: new Blob([text]),
|
|
@@ -295,10 +293,8 @@ export const getCopyHelper = (qb: QB) => {
|
|
|
295
293
|
} else {
|
|
296
294
|
return async (table: Table, text: string, includeSchema = true) => {
|
|
297
295
|
const target = includeSchema
|
|
298
|
-
? `"${getTableConfig(table).schema ?? "public"}"."${getTableName(
|
|
299
|
-
|
|
300
|
-
)}"`
|
|
301
|
-
: `"${getTableName(table)}"`;
|
|
296
|
+
? `"${getTableConfig(table).schema ?? "public"}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"`
|
|
297
|
+
: `"${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"`;
|
|
302
298
|
const copyStream = qb.$client.query(
|
|
303
299
|
copy.from(`COPY ${target} FROM STDIN`),
|
|
304
300
|
);
|
|
@@ -348,11 +344,13 @@ export const createIndexingCache = ({
|
|
|
348
344
|
schemaBuild: { schema },
|
|
349
345
|
crashRecoveryCheckpoint,
|
|
350
346
|
eventCount,
|
|
347
|
+
chainId,
|
|
351
348
|
}: {
|
|
352
349
|
common: Common;
|
|
353
350
|
schemaBuild: Pick<SchemaBuild, "schema">;
|
|
354
351
|
crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
|
|
355
352
|
eventCount: { [eventName: string]: number };
|
|
353
|
+
chainId?: number;
|
|
356
354
|
}): IndexingCache => {
|
|
357
355
|
let event: Event | undefined;
|
|
358
356
|
let qb: QB = undefined!;
|
|
@@ -363,8 +361,6 @@ export const createIndexingCache = ({
|
|
|
363
361
|
/** Profiling data about access patterns for each event. */
|
|
364
362
|
const profile: Profile = new Map();
|
|
365
363
|
|
|
366
|
-
let isFlushRetry = false;
|
|
367
|
-
|
|
368
364
|
const tables = Object.values(schema).filter(isTable);
|
|
369
365
|
const primaryKeyCache = getPrimaryKeyCache(tables);
|
|
370
366
|
|
|
@@ -393,11 +389,14 @@ export const createIndexingCache = ({
|
|
|
393
389
|
);
|
|
394
390
|
},
|
|
395
391
|
async get({ table, key }) {
|
|
396
|
-
if (
|
|
397
|
-
|
|
398
|
-
|
|
392
|
+
if (
|
|
393
|
+
event &&
|
|
394
|
+
eventCount[event.eventCallback.name]! % SAMPLING_RATE === 1
|
|
395
|
+
) {
|
|
396
|
+
if (profile.has(event.eventCallback.name) === false) {
|
|
397
|
+
profile.set(event.eventCallback.name, new Map());
|
|
399
398
|
for (const table of tables) {
|
|
400
|
-
profile.get(event.name)!.set(table, new Map());
|
|
399
|
+
profile.get(event.eventCallback.name)!.set(table, new Map());
|
|
401
400
|
}
|
|
402
401
|
}
|
|
403
402
|
|
|
@@ -405,18 +404,19 @@ export const createIndexingCache = ({
|
|
|
405
404
|
event,
|
|
406
405
|
table,
|
|
407
406
|
key,
|
|
408
|
-
Array.from(
|
|
409
|
-
(
|
|
410
|
-
),
|
|
407
|
+
Array.from(
|
|
408
|
+
profile.get(event.eventCallback.name)!.get(table)!.values(),
|
|
409
|
+
).map(({ pattern }) => pattern),
|
|
411
410
|
primaryKeyCache,
|
|
412
411
|
);
|
|
413
412
|
if (pattern) {
|
|
414
413
|
const key = getProfilePatternKey(pattern);
|
|
415
|
-
if (profile.get(event.name)!.get(table)!.has(key)) {
|
|
416
|
-
profile.get(event.name)!.get(table)!.get(key)
|
|
414
|
+
if (profile.get(event.eventCallback.name)!.get(table)!.has(key)) {
|
|
415
|
+
profile.get(event.eventCallback.name)!.get(table)!.get(key)!
|
|
416
|
+
.count++;
|
|
417
417
|
} else {
|
|
418
418
|
profile
|
|
419
|
-
.get(event.name)!
|
|
419
|
+
.get(event.eventCallback.name)!
|
|
420
420
|
.get(table)!
|
|
421
421
|
.set(key, { pattern, count: 1 });
|
|
422
422
|
}
|
|
@@ -530,150 +530,86 @@ export const createIndexingCache = ({
|
|
|
530
530
|
};
|
|
531
531
|
const flushEndClock = startClock();
|
|
532
532
|
|
|
533
|
-
const copy = getCopyHelper(qb);
|
|
534
|
-
|
|
535
|
-
// Note `isFlushRetry` is true when the previous flush failed. When `isFlushRetry` is false, this
|
|
536
|
-
// function takes an optimized fast path, with support for small batch sizes. PGlite always takes
|
|
537
|
-
// the fast path because it doesn't support delayed insert errors.
|
|
538
|
-
|
|
539
|
-
if (isFlushRetry && qb.$dialect === "postgres") {
|
|
540
|
-
for (const table of cache.keys()) {
|
|
541
|
-
const shouldRecordBytes = cache.get(table)!.isCacheComplete;
|
|
542
|
-
if (
|
|
543
|
-
tableNames !== undefined &&
|
|
544
|
-
tableNames.has(getTableName(table)) === false
|
|
545
|
-
) {
|
|
546
|
-
continue;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const tableCache = cache.get(table)!;
|
|
550
|
-
|
|
551
|
-
const insertValues = Array.from(insertBuffer.get(table)!.values());
|
|
552
|
-
const updateValues = Array.from(updateBuffer.get(table)!.values());
|
|
553
|
-
|
|
554
|
-
if (insertValues.length > 0) {
|
|
555
|
-
const endClock = startClock();
|
|
533
|
+
const copy = getCopyHelper(qb, chainId);
|
|
556
534
|
|
|
557
|
-
|
|
535
|
+
const flushTable = async (table: Table) => {
|
|
536
|
+
const shouldRecordBytes = cache.get(table)!.isCacheComplete;
|
|
537
|
+
if (
|
|
538
|
+
tableNames !== undefined &&
|
|
539
|
+
tableNames.has(getTableName(table)) === false
|
|
540
|
+
) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
558
543
|
|
|
559
|
-
|
|
560
|
-
const text = getCopyText(
|
|
561
|
-
table,
|
|
562
|
-
insertValues.map(({ row }) => row),
|
|
563
|
-
);
|
|
544
|
+
const tableCache = cache.get(table)!;
|
|
564
545
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
let error = _error as Error;
|
|
570
|
-
const result = await recoverBatchError(
|
|
571
|
-
insertValues,
|
|
572
|
-
async (values) => {
|
|
573
|
-
await qb.wrap(
|
|
574
|
-
(db) => db.execute("ROLLBACK to flush"),
|
|
575
|
-
context,
|
|
576
|
-
);
|
|
577
|
-
const text = getCopyText(
|
|
578
|
-
table,
|
|
579
|
-
values.map(({ row }) => row),
|
|
580
|
-
);
|
|
581
|
-
await copy(table, text);
|
|
582
|
-
|
|
583
|
-
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
584
|
-
},
|
|
585
|
-
);
|
|
546
|
+
const target =
|
|
547
|
+
chainId === undefined
|
|
548
|
+
? getTableName(table)
|
|
549
|
+
: getPartitionName(table, chainId);
|
|
586
550
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
error.stack = undefined;
|
|
551
|
+
const insertValues = Array.from(insertBuffer.get(table)!.values());
|
|
552
|
+
const updateValues = Array.from(updateBuffer.get(table)!.values());
|
|
590
553
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
`db.insert arguments:\n${prettyPrint(result.value.row)}`,
|
|
594
|
-
);
|
|
554
|
+
if (insertValues.length > 0) {
|
|
555
|
+
const endClock = startClock();
|
|
595
556
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
event: result.value.metadata.event.name,
|
|
602
|
-
type: "insert",
|
|
603
|
-
table: getTableName(table),
|
|
604
|
-
row_count: insertValues.length,
|
|
605
|
-
duration: endClock(),
|
|
606
|
-
error,
|
|
607
|
-
});
|
|
608
|
-
} else {
|
|
609
|
-
common.logger.warn({
|
|
610
|
-
msg: "Failed to write cached database rows",
|
|
611
|
-
type: "insert",
|
|
612
|
-
table: getTableName(table),
|
|
613
|
-
row_count: insertValues.length,
|
|
614
|
-
duration: endClock(),
|
|
615
|
-
error,
|
|
616
|
-
});
|
|
617
|
-
}
|
|
557
|
+
if (insertValues.length > LOW_BATCH_THRESHOLD) {
|
|
558
|
+
const text = getCopyText(
|
|
559
|
+
table,
|
|
560
|
+
insertValues.map(({ row }) => row),
|
|
561
|
+
);
|
|
618
562
|
|
|
619
|
-
|
|
620
|
-
error.meta = undefined;
|
|
621
|
-
} else {
|
|
622
|
-
error.stack = undefined;
|
|
563
|
+
await new Promise(setImmediate);
|
|
623
564
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
565
|
+
await copy(table, text);
|
|
566
|
+
} else {
|
|
567
|
+
await qb.wrap(
|
|
568
|
+
(db) =>
|
|
569
|
+
db.insert(table).values(insertValues.map(({ row }) => row)),
|
|
570
|
+
context,
|
|
571
|
+
);
|
|
572
|
+
}
|
|
633
573
|
|
|
634
|
-
|
|
574
|
+
common.metrics.ponder_indexing_cache_query_duration.observe(
|
|
575
|
+
{
|
|
576
|
+
table: getTableName(table),
|
|
577
|
+
method: "flush",
|
|
578
|
+
},
|
|
579
|
+
endClock(),
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
let bytes = 0;
|
|
583
|
+
for (const [key, entry] of insertBuffer.get(table)!) {
|
|
584
|
+
if (shouldRecordBytes && tableCache.cache.has(key) === false) {
|
|
585
|
+
bytes += getBytes(entry.row) + getBytes(key);
|
|
635
586
|
}
|
|
587
|
+
tableCache.cache.set(key, entry.row);
|
|
588
|
+
}
|
|
589
|
+
tableCache.bytes += bytes;
|
|
590
|
+
insertBuffer.get(table)!.clear();
|
|
636
591
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
table: getTableName(table),
|
|
640
|
-
method: "flush",
|
|
641
|
-
},
|
|
642
|
-
endClock(),
|
|
643
|
-
);
|
|
592
|
+
await new Promise(setImmediate);
|
|
593
|
+
}
|
|
644
594
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (shouldRecordBytes && tableCache.cache.has(key) === false) {
|
|
648
|
-
bytes += getBytes(entry.row) + getBytes(key);
|
|
649
|
-
}
|
|
650
|
-
tableCache.cache.set(key, entry.row);
|
|
651
|
-
}
|
|
652
|
-
tableCache.bytes += bytes;
|
|
653
|
-
insertBuffer.get(table)!.clear();
|
|
595
|
+
if (updateValues.length > 0) {
|
|
596
|
+
const primaryKeys = getPrimaryKeyColumns(table);
|
|
654
597
|
|
|
655
|
-
|
|
656
|
-
}
|
|
598
|
+
const endClock = startClock();
|
|
657
599
|
|
|
658
|
-
if (updateValues.length >
|
|
600
|
+
if (updateValues.length > LOW_BATCH_THRESHOLD) {
|
|
659
601
|
// Steps for flushing "update" entries:
|
|
660
602
|
// 1. Create temp table
|
|
661
603
|
// 2. Copy into temp table
|
|
662
604
|
// 3. Update target table with data from temp
|
|
663
605
|
|
|
664
|
-
const primaryKeys = getPrimaryKeyColumns(table);
|
|
665
|
-
|
|
666
606
|
const createTempTableQuery = `
|
|
667
|
-
CREATE TEMP TABLE IF NOT EXISTS "${
|
|
668
|
-
AS SELECT * FROM "${
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
WITH NO DATA;
|
|
672
|
-
`;
|
|
607
|
+
CREATE TEMP TABLE IF NOT EXISTS "${target}"
|
|
608
|
+
AS SELECT * FROM "${getTableConfig(table).schema ?? "public"}"."${target}"
|
|
609
|
+
WITH NO DATA;`;
|
|
610
|
+
|
|
673
611
|
const updateQuery = `
|
|
674
|
-
UPDATE "${
|
|
675
|
-
getTableConfig(table).schema ?? "public"
|
|
676
|
-
}"."${getTableName(table)}" as target
|
|
612
|
+
UPDATE "${getTableConfig(table).schema ?? "public"}"."${target}" as target
|
|
677
613
|
SET ${Object.values(getTableColumns(table))
|
|
678
614
|
.map(
|
|
679
615
|
(column) =>
|
|
@@ -683,321 +619,255 @@ export const createIndexingCache = ({
|
|
|
683
619
|
)}" = source."${getColumnCasing(column, "snake_case")}"`,
|
|
684
620
|
)
|
|
685
621
|
.join(",\n")}
|
|
686
|
-
FROM "${
|
|
622
|
+
FROM "${target}" source
|
|
687
623
|
WHERE ${primaryKeys
|
|
688
624
|
.map(({ sql }) => `target."${sql}" = source."${sql}"`)
|
|
689
|
-
.join(" AND ")}
|
|
690
|
-
`;
|
|
691
|
-
|
|
692
|
-
const endClock = startClock();
|
|
625
|
+
.join(" AND ")};`;
|
|
693
626
|
|
|
694
627
|
await qb.wrap((db) => db.execute(createTempTableQuery), context);
|
|
695
|
-
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
696
|
-
|
|
697
|
-
try {
|
|
698
|
-
const text = getCopyText(
|
|
699
|
-
table,
|
|
700
|
-
updateValues.map(({ row }) => row),
|
|
701
|
-
);
|
|
702
|
-
|
|
703
|
-
await new Promise(setImmediate);
|
|
704
|
-
|
|
705
|
-
await copy(table, text, false);
|
|
706
|
-
} catch (_error) {
|
|
707
|
-
let error = _error as Error;
|
|
708
|
-
const result = await recoverBatchError(
|
|
709
|
-
updateValues,
|
|
710
|
-
async (values) => {
|
|
711
|
-
await qb.wrap(
|
|
712
|
-
(db) => db.execute("ROLLBACK to flush"),
|
|
713
|
-
context,
|
|
714
|
-
);
|
|
715
|
-
const text = getCopyText(
|
|
716
|
-
table,
|
|
717
|
-
values.map(({ row }) => row),
|
|
718
|
-
);
|
|
719
|
-
await copy(table, text, false);
|
|
720
|
-
|
|
721
|
-
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
722
|
-
},
|
|
723
|
-
);
|
|
724
|
-
|
|
725
|
-
if (result.status === "error") {
|
|
726
|
-
error = new DelayedInsertError(result.error.message);
|
|
727
|
-
error.stack = undefined;
|
|
728
|
-
|
|
729
|
-
addErrorMeta(
|
|
730
|
-
error,
|
|
731
|
-
`db.update arguments:\n${prettyPrint(result.value.row)}`,
|
|
732
|
-
);
|
|
733
|
-
|
|
734
|
-
if (result.value.metadata.event) {
|
|
735
|
-
addErrorMeta(error, toErrorMeta(result.value.metadata.event));
|
|
736
|
-
|
|
737
|
-
common.logger.warn({
|
|
738
|
-
msg: "Failed to write cached database rows",
|
|
739
|
-
event: result.value.metadata.event.name,
|
|
740
|
-
type: "update",
|
|
741
|
-
table: getTableName(table),
|
|
742
|
-
row_count: updateValues.length,
|
|
743
|
-
duration: endClock(),
|
|
744
|
-
error,
|
|
745
|
-
});
|
|
746
|
-
} else {
|
|
747
|
-
common.logger.warn({
|
|
748
|
-
msg: "Failed to write cached database rows",
|
|
749
|
-
type: "update",
|
|
750
|
-
table: getTableName(table),
|
|
751
|
-
row_count: updateValues.length,
|
|
752
|
-
duration: endClock(),
|
|
753
|
-
error,
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// @ts-ignore remove meta from error
|
|
758
|
-
error.meta = undefined;
|
|
759
|
-
} else {
|
|
760
|
-
error.stack = undefined;
|
|
761
|
-
|
|
762
|
-
common.logger.warn({
|
|
763
|
-
msg: "Failed to write cached database rows",
|
|
764
|
-
type: "update",
|
|
765
|
-
table: getTableName(table),
|
|
766
|
-
row_count: updateValues.length,
|
|
767
|
-
duration: endClock(),
|
|
768
|
-
error,
|
|
769
|
-
});
|
|
770
|
-
}
|
|
771
628
|
|
|
772
|
-
|
|
773
|
-
|
|
629
|
+
const text = getCopyText(
|
|
630
|
+
table,
|
|
631
|
+
updateValues.map(({ row }) => row),
|
|
632
|
+
);
|
|
633
|
+
await new Promise(setImmediate);
|
|
774
634
|
|
|
635
|
+
await copy(table, text, false);
|
|
775
636
|
await qb.wrap((db) => db.execute(updateQuery), context);
|
|
776
637
|
await qb.wrap(
|
|
777
|
-
(db) => db.execute(`TRUNCATE TABLE "${
|
|
638
|
+
(db) => db.execute(`TRUNCATE TABLE "${target}"`),
|
|
778
639
|
context,
|
|
779
640
|
);
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
641
|
+
} else {
|
|
642
|
+
await qb.wrap(
|
|
643
|
+
(db) =>
|
|
644
|
+
db
|
|
645
|
+
.insert(table)
|
|
646
|
+
.values(updateValues.map(({ row }) => row))
|
|
647
|
+
.onConflictDoUpdate({
|
|
648
|
+
// @ts-ignore
|
|
649
|
+
target: primaryKeys.map(({ js }) => table[js]!),
|
|
650
|
+
set: Object.fromEntries(
|
|
651
|
+
Object.entries(getTableColumns(table)).map(
|
|
652
|
+
([columnName, column]) => [
|
|
653
|
+
columnName,
|
|
654
|
+
sql.raw(
|
|
655
|
+
`excluded."${getColumnCasing(column, "snake_case")}"`,
|
|
656
|
+
),
|
|
657
|
+
],
|
|
658
|
+
),
|
|
659
|
+
),
|
|
660
|
+
}),
|
|
661
|
+
context,
|
|
787
662
|
);
|
|
663
|
+
}
|
|
788
664
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
665
|
+
common.metrics.ponder_indexing_cache_query_duration.observe(
|
|
666
|
+
{
|
|
667
|
+
table: getTableName(table),
|
|
668
|
+
method: "flush",
|
|
669
|
+
},
|
|
670
|
+
endClock(),
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
let bytes = 0;
|
|
674
|
+
for (const [key, entry] of updateBuffer.get(table)!) {
|
|
675
|
+
if (shouldRecordBytes && tableCache.cache.has(key) === false) {
|
|
676
|
+
bytes += getBytes(entry.row) + getBytes(key);
|
|
795
677
|
}
|
|
796
|
-
tableCache.
|
|
797
|
-
updateBuffer.get(table)!.clear();
|
|
798
|
-
|
|
799
|
-
await new Promise(setImmediate);
|
|
678
|
+
tableCache.cache.set(key, entry.row);
|
|
800
679
|
}
|
|
680
|
+
tableCache.bytes += bytes;
|
|
681
|
+
updateBuffer.get(table)!.clear();
|
|
801
682
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
msg: "Wrote database rows",
|
|
805
|
-
table: getTableName(table),
|
|
806
|
-
row_count: insertValues.length + updateValues.length,
|
|
807
|
-
duration: flushEndClock(),
|
|
808
|
-
});
|
|
683
|
+
await new Promise(setImmediate);
|
|
684
|
+
}
|
|
809
685
|
|
|
810
|
-
|
|
686
|
+
if (insertValues.length > 0 || updateValues.length > 0) {
|
|
687
|
+
common.logger.debug({
|
|
688
|
+
msg: "Wrote database rows",
|
|
689
|
+
table: target,
|
|
690
|
+
row_count: insertValues.length + updateValues.length,
|
|
691
|
+
duration: flushEndClock(),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
try {
|
|
697
|
+
if (qb.$dialect === "postgres") {
|
|
698
|
+
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
699
|
+
|
|
700
|
+
await promiseAllSettledWithThrow(
|
|
701
|
+
Array.from(cache.keys()).map(flushTable),
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
await qb.wrap((db) => db.execute("RELEASE flush"), context);
|
|
705
|
+
} else {
|
|
706
|
+
// Note: pglite must run sequentially
|
|
707
|
+
for (const table of cache.keys()) {
|
|
708
|
+
await flushTable(table);
|
|
811
709
|
}
|
|
812
710
|
}
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
711
|
+
} catch (_error) {
|
|
712
|
+
let error = _error as Error;
|
|
713
|
+
if (error instanceof ShutdownError || qb.$dialect === "pglite") {
|
|
714
|
+
throw error;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Note `isFlushRetry` is true when the previous flush failed. When `isFlushRetry` is false, this
|
|
718
|
+
// function takes an optimized fast path, with support for small batch sizes. PGlite always takes
|
|
719
|
+
// the fast path because it doesn't support delayed insert errors.
|
|
720
|
+
|
|
721
|
+
await qb.wrap((db) => db.execute("ROLLBACK to flush"), context);
|
|
722
|
+
|
|
723
|
+
for (const table of cache.keys()) {
|
|
724
|
+
if (
|
|
725
|
+
tableNames !== undefined &&
|
|
726
|
+
tableNames.has(getTableName(table)) === false
|
|
727
|
+
) {
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
827
730
|
|
|
828
|
-
|
|
731
|
+
const target =
|
|
732
|
+
chainId === undefined
|
|
733
|
+
? getTableName(table)
|
|
734
|
+
: getPartitionName(table, chainId);
|
|
735
|
+
|
|
736
|
+
const insertValues = Array.from(insertBuffer.get(table)!.values());
|
|
737
|
+
const updateValues = Array.from(updateBuffer.get(table)!.values());
|
|
829
738
|
|
|
830
|
-
|
|
831
|
-
const
|
|
739
|
+
if (insertValues.length > 0) {
|
|
740
|
+
const endClock = startClock();
|
|
832
741
|
|
|
833
|
-
|
|
834
|
-
const endClock = startClock();
|
|
742
|
+
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
835
743
|
|
|
836
|
-
|
|
744
|
+
const result = await recoverBatchError(
|
|
745
|
+
insertValues,
|
|
746
|
+
async (values) => {
|
|
747
|
+
await qb.wrap((db) => db.execute("ROLLBACK to flush"), context);
|
|
837
748
|
const text = getCopyText(
|
|
838
749
|
table,
|
|
839
|
-
|
|
750
|
+
values.map(({ row }) => row),
|
|
840
751
|
);
|
|
752
|
+
await copy(table, text);
|
|
841
753
|
|
|
842
|
-
await
|
|
754
|
+
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
755
|
+
},
|
|
756
|
+
);
|
|
843
757
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
(db) =>
|
|
848
|
-
db.insert(table).values(insertValues.map(({ row }) => row)),
|
|
849
|
-
context,
|
|
850
|
-
);
|
|
851
|
-
}
|
|
758
|
+
if (result.status === "error") {
|
|
759
|
+
error = new DelayedInsertError(result.error.message);
|
|
760
|
+
error.stack = undefined;
|
|
852
761
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
method: "flush",
|
|
857
|
-
},
|
|
858
|
-
endClock(),
|
|
762
|
+
addErrorMeta(
|
|
763
|
+
error,
|
|
764
|
+
`db.insert arguments:\n${prettyPrint(result.value.row)}`,
|
|
859
765
|
);
|
|
860
766
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
767
|
+
if (result.value.metadata.event) {
|
|
768
|
+
addErrorMeta(error, toErrorMeta(result.value.metadata.event));
|
|
769
|
+
|
|
770
|
+
common.logger.warn({
|
|
771
|
+
msg: "Failed to write cached database rows",
|
|
772
|
+
event: result.value.metadata.event.eventCallback.name,
|
|
773
|
+
type: "insert",
|
|
774
|
+
table: getTableName(table),
|
|
775
|
+
row_count: insertValues.length,
|
|
776
|
+
duration: endClock(),
|
|
777
|
+
error,
|
|
778
|
+
});
|
|
779
|
+
} else {
|
|
780
|
+
common.logger.warn({
|
|
781
|
+
msg: "Failed to write cached database rows",
|
|
782
|
+
type: "insert",
|
|
783
|
+
table: getTableName(table),
|
|
784
|
+
row_count: insertValues.length,
|
|
785
|
+
duration: endClock(),
|
|
786
|
+
error,
|
|
787
|
+
});
|
|
867
788
|
}
|
|
868
|
-
tableCache.bytes += bytes;
|
|
869
|
-
insertBuffer.get(table)!.clear();
|
|
870
789
|
|
|
871
|
-
|
|
790
|
+
throw error;
|
|
872
791
|
}
|
|
792
|
+
}
|
|
873
793
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
const createTempTableQuery = `
|
|
886
|
-
CREATE TEMP TABLE IF NOT EXISTS "${getTableName(table)}"
|
|
887
|
-
AS SELECT * FROM "${
|
|
888
|
-
getTableConfig(table).schema ?? "public"
|
|
889
|
-
}"."${getTableName(table)}"
|
|
890
|
-
WITH NO DATA;
|
|
891
|
-
`;
|
|
892
|
-
|
|
893
|
-
const updateQuery = `
|
|
894
|
-
UPDATE "${
|
|
895
|
-
getTableConfig(table).schema ?? "public"
|
|
896
|
-
}"."${getTableName(table)}" as target
|
|
897
|
-
SET ${Object.values(getTableColumns(table))
|
|
898
|
-
.map(
|
|
899
|
-
(column) =>
|
|
900
|
-
`"${getColumnCasing(
|
|
901
|
-
column,
|
|
902
|
-
"snake_case",
|
|
903
|
-
)}" = source."${getColumnCasing(column, "snake_case")}"`,
|
|
904
|
-
)
|
|
905
|
-
.join(",\n")}
|
|
906
|
-
FROM "${getTableName(table)}" source
|
|
907
|
-
WHERE ${primaryKeys
|
|
908
|
-
.map(({ sql }) => `target."${sql}" = source."${sql}"`)
|
|
909
|
-
.join(" AND ")};
|
|
910
|
-
`;
|
|
911
|
-
|
|
912
|
-
await qb.wrap(
|
|
913
|
-
(db) => db.execute(createTempTableQuery),
|
|
914
|
-
context,
|
|
915
|
-
);
|
|
794
|
+
if (updateValues.length > 0) {
|
|
795
|
+
// Steps for flushing "update" entries:
|
|
796
|
+
// 1. Create temp table
|
|
797
|
+
// 2. Copy into temp table
|
|
798
|
+
// 3. Update target table with data from temp
|
|
799
|
+
|
|
800
|
+
const createTempTableQuery = `
|
|
801
|
+
CREATE TEMP TABLE IF NOT EXISTS "${target}"
|
|
802
|
+
AS SELECT * FROM "${getTableConfig(table).schema ?? "public"}"."${target}"
|
|
803
|
+
WITH NO DATA;
|
|
804
|
+
`;
|
|
916
805
|
|
|
806
|
+
const endClock = startClock();
|
|
807
|
+
|
|
808
|
+
await qb.wrap((db) => db.execute(createTempTableQuery), context);
|
|
809
|
+
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
810
|
+
|
|
811
|
+
const result = await recoverBatchError(
|
|
812
|
+
updateValues,
|
|
813
|
+
async (values) => {
|
|
814
|
+
await qb.wrap((db) => db.execute("ROLLBACK to flush"), context);
|
|
917
815
|
const text = getCopyText(
|
|
918
816
|
table,
|
|
919
|
-
|
|
817
|
+
values.map(({ row }) => row),
|
|
920
818
|
);
|
|
921
|
-
|
|
922
|
-
await new Promise(setImmediate);
|
|
923
|
-
|
|
924
819
|
await copy(table, text, false);
|
|
925
820
|
|
|
926
|
-
await qb.wrap((db) => db.execute(
|
|
821
|
+
await qb.wrap((db) => db.execute("SAVEPOINT flush"), context);
|
|
822
|
+
},
|
|
823
|
+
);
|
|
927
824
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
} else {
|
|
933
|
-
await qb.wrap(
|
|
934
|
-
(db) =>
|
|
935
|
-
db
|
|
936
|
-
.insert(table)
|
|
937
|
-
.values(updateValues.map(({ row }) => row))
|
|
938
|
-
.onConflictDoUpdate({
|
|
939
|
-
// @ts-ignore
|
|
940
|
-
target: primaryKeys.map(({ js }) => table[js]!),
|
|
941
|
-
set: Object.fromEntries(
|
|
942
|
-
Object.entries(getTableColumns(table)).map(
|
|
943
|
-
([columnName, column]) => [
|
|
944
|
-
columnName,
|
|
945
|
-
sql.raw(
|
|
946
|
-
`excluded."${getColumnCasing(column, "snake_case")}"`,
|
|
947
|
-
),
|
|
948
|
-
],
|
|
949
|
-
),
|
|
950
|
-
),
|
|
951
|
-
}),
|
|
952
|
-
context,
|
|
953
|
-
);
|
|
954
|
-
}
|
|
825
|
+
await qb.wrap(
|
|
826
|
+
(db) => db.execute(`TRUNCATE TABLE "${target}"`),
|
|
827
|
+
context,
|
|
828
|
+
);
|
|
955
829
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
830
|
+
if (result.status === "error") {
|
|
831
|
+
error = new DelayedInsertError(result.error.message);
|
|
832
|
+
error.stack = undefined;
|
|
833
|
+
|
|
834
|
+
addErrorMeta(
|
|
835
|
+
error,
|
|
836
|
+
`db.update arguments:\n${prettyPrint(result.value.row)}`,
|
|
962
837
|
);
|
|
963
838
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if (shouldRecordBytes && tableCache.cache.has(key) === false) {
|
|
967
|
-
bytes += getBytes(entry.row) + getBytes(key);
|
|
968
|
-
}
|
|
969
|
-
tableCache.cache.set(key, entry.row);
|
|
970
|
-
}
|
|
971
|
-
tableCache.bytes += bytes;
|
|
972
|
-
updateBuffer.get(table)!.clear();
|
|
839
|
+
if (result.value.metadata.event) {
|
|
840
|
+
addErrorMeta(error, toErrorMeta(result.value.metadata.event));
|
|
973
841
|
|
|
974
|
-
|
|
975
|
-
|
|
842
|
+
common.logger.warn({
|
|
843
|
+
msg: "Failed to write cached database rows",
|
|
844
|
+
event: result.value.metadata.event.eventCallback.name,
|
|
845
|
+
type: "update",
|
|
846
|
+
table: getTableName(table),
|
|
847
|
+
row_count: updateValues.length,
|
|
848
|
+
duration: endClock(),
|
|
849
|
+
error,
|
|
850
|
+
});
|
|
851
|
+
} else {
|
|
852
|
+
common.logger.warn({
|
|
853
|
+
msg: "Failed to write cached database rows",
|
|
854
|
+
type: "update",
|
|
855
|
+
table: getTableName(table),
|
|
856
|
+
row_count: updateValues.length,
|
|
857
|
+
duration: endClock(),
|
|
858
|
+
error,
|
|
859
|
+
});
|
|
860
|
+
}
|
|
976
861
|
|
|
977
|
-
|
|
978
|
-
common.logger.debug({
|
|
979
|
-
msg: "Wrote database rows",
|
|
980
|
-
table: getTableName(table),
|
|
981
|
-
row_count: insertValues.length + updateValues.length,
|
|
982
|
-
duration: flushEndClock(),
|
|
983
|
-
});
|
|
862
|
+
throw error;
|
|
984
863
|
}
|
|
985
|
-
}),
|
|
986
|
-
);
|
|
987
|
-
|
|
988
|
-
if (results.some((result) => result.status === "rejected")) {
|
|
989
|
-
const rejected = results.find(
|
|
990
|
-
(result): result is PromiseRejectedResult =>
|
|
991
|
-
result.status === "rejected",
|
|
992
|
-
)!;
|
|
993
|
-
if (rejected.reason instanceof ShutdownError) {
|
|
994
|
-
throw rejected.reason;
|
|
995
864
|
}
|
|
996
|
-
throw new RetryableError(rejected.reason.message);
|
|
997
865
|
}
|
|
998
|
-
}
|
|
999
866
|
|
|
1000
|
-
|
|
867
|
+
// Note: if we weren't able to find the exact row that caused the error,
|
|
868
|
+
// throw the original error.
|
|
869
|
+
throw error;
|
|
870
|
+
}
|
|
1001
871
|
},
|
|
1002
872
|
async prefetch({ events }) {
|
|
1003
873
|
const context = {
|
|
@@ -1050,14 +920,15 @@ export const createIndexingCache = ({
|
|
|
1050
920
|
}
|
|
1051
921
|
|
|
1052
922
|
for (const event of events) {
|
|
1053
|
-
if (profile.has(event.name)) {
|
|
923
|
+
if (profile.has(event.eventCallback.name)) {
|
|
1054
924
|
for (const table of tables) {
|
|
1055
925
|
if (cache.get(table)!.isCacheComplete) continue;
|
|
1056
926
|
for (const [, { count, pattern }] of profile
|
|
1057
|
-
.get(event.name)!
|
|
927
|
+
.get(event.eventCallback.name)!
|
|
1058
928
|
.get(table)!) {
|
|
1059
929
|
// Expected value of times the prediction will be used.
|
|
1060
|
-
const ev =
|
|
930
|
+
const ev =
|
|
931
|
+
(count * SAMPLING_RATE) / eventCount[event.eventCallback.name]!;
|
|
1061
932
|
if (ev > PREDICTION_THRESHOLD) {
|
|
1062
933
|
const row = recoverProfilePattern(pattern, event);
|
|
1063
934
|
const key = getCacheKey(table, row, primaryKeyCache);
|