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
package/src/database/actions.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
getPartitionName,
|
|
3
|
+
getPrimaryKeyColumns,
|
|
4
|
+
getReorgProcedureName,
|
|
5
|
+
getReorgTableName,
|
|
6
|
+
getReorgTriggerName,
|
|
7
|
+
} from "@/drizzle/index.js";
|
|
3
8
|
import { getColumnCasing, getReorgTable } from "@/drizzle/kit/index.js";
|
|
9
|
+
import {
|
|
10
|
+
getLiveQueryChannelName,
|
|
11
|
+
getLiveQueryNotifyProcedureName,
|
|
12
|
+
getLiveQueryNotifyTriggerName,
|
|
13
|
+
getLiveQueryProcedureName,
|
|
14
|
+
getLiveQueryTriggerName,
|
|
15
|
+
getViewsLiveQueryNotifyTriggerName,
|
|
16
|
+
} from "@/drizzle/onchain.js";
|
|
4
17
|
import type { Logger } from "@/internal/logger.js";
|
|
5
18
|
import type {
|
|
6
19
|
NamespaceBuild,
|
|
@@ -9,12 +22,16 @@ import type {
|
|
|
9
22
|
} from "@/internal/types.js";
|
|
10
23
|
import { MAX_CHECKPOINT_STRING, decodeCheckpoint } from "@/utils/checkpoint.js";
|
|
11
24
|
import {
|
|
25
|
+
type SQL,
|
|
12
26
|
type Table,
|
|
13
27
|
type View,
|
|
28
|
+
and,
|
|
14
29
|
eq,
|
|
15
30
|
getTableColumns,
|
|
16
31
|
getTableName,
|
|
17
32
|
getViewName,
|
|
33
|
+
lte,
|
|
34
|
+
sql,
|
|
18
35
|
} from "drizzle-orm";
|
|
19
36
|
import { getTableConfig } from "drizzle-orm/pg-core";
|
|
20
37
|
import { getPonderCheckpointTable } from "./index.js";
|
|
@@ -41,7 +58,7 @@ export const createIndexes = async (
|
|
|
41
58
|
|
|
42
59
|
export const createTriggers = async (
|
|
43
60
|
qb: QB,
|
|
44
|
-
{ tables }: { tables: Table[] },
|
|
61
|
+
{ tables, chainId }: { tables: Table[]; chainId?: number },
|
|
45
62
|
context?: { logger?: Logger },
|
|
46
63
|
) => {
|
|
47
64
|
await qb.transaction(
|
|
@@ -58,17 +75,17 @@ export const createTriggers = async (
|
|
|
58
75
|
await tx.wrap({ label: "create_trigger" }, (tx) =>
|
|
59
76
|
tx.execute(
|
|
60
77
|
`
|
|
61
|
-
CREATE OR REPLACE FUNCTION "${schema}".${
|
|
78
|
+
CREATE OR REPLACE FUNCTION "${schema}".${getReorgProcedureName(table)}
|
|
62
79
|
RETURNS TRIGGER AS $$
|
|
63
80
|
BEGIN
|
|
64
81
|
IF TG_OP = 'INSERT' THEN
|
|
65
|
-
INSERT INTO "${schema}"."${
|
|
82
|
+
INSERT INTO "${schema}"."${getReorgTableName(table)}" (${columnNames.join(",")}, operation, checkpoint)
|
|
66
83
|
VALUES (${columnNames.map((name) => `NEW.${name}`).join(",")}, 0, '${MAX_CHECKPOINT_STRING}');
|
|
67
84
|
ELSIF TG_OP = 'UPDATE' THEN
|
|
68
|
-
INSERT INTO "${schema}"."${
|
|
85
|
+
INSERT INTO "${schema}"."${getReorgTableName(table)}" (${columnNames.join(",")}, operation, checkpoint)
|
|
69
86
|
VALUES (${columnNames.map((name) => `OLD.${name}`).join(",")}, 1, '${MAX_CHECKPOINT_STRING}');
|
|
70
87
|
ELSIF TG_OP = 'DELETE' THEN
|
|
71
|
-
INSERT INTO "${schema}"."${
|
|
88
|
+
INSERT INTO "${schema}"."${getReorgTableName(table)}" (${columnNames.join(",")}, operation, checkpoint)
|
|
72
89
|
VALUES (${columnNames.map((name) => `OLD.${name}`).join(",")}, 2, '${MAX_CHECKPOINT_STRING}');
|
|
73
90
|
END IF;
|
|
74
91
|
RETURN NULL;
|
|
@@ -80,9 +97,9 @@ export const createTriggers = async (
|
|
|
80
97
|
await tx.wrap({ label: "create_trigger" }, (tx) =>
|
|
81
98
|
tx.execute(
|
|
82
99
|
`
|
|
83
|
-
CREATE OR REPLACE TRIGGER "${
|
|
84
|
-
AFTER INSERT OR UPDATE OR DELETE ON "${schema}"."${getTableName(table)}"
|
|
85
|
-
FOR EACH ROW EXECUTE FUNCTION "${schema}".${
|
|
100
|
+
CREATE OR REPLACE TRIGGER "${getReorgTriggerName()}"
|
|
101
|
+
AFTER INSERT OR UPDATE OR DELETE ON "${schema}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"
|
|
102
|
+
FOR EACH ROW EXECUTE FUNCTION "${schema}".${getReorgProcedureName(table)};
|
|
86
103
|
`,
|
|
87
104
|
),
|
|
88
105
|
);
|
|
@@ -96,7 +113,7 @@ export const createTriggers = async (
|
|
|
96
113
|
|
|
97
114
|
export const dropTriggers = async (
|
|
98
115
|
qb: QB,
|
|
99
|
-
{ tables }: { tables: Table[] },
|
|
116
|
+
{ tables, chainId }: { tables: Table[]; chainId?: number },
|
|
100
117
|
context?: { logger?: Logger },
|
|
101
118
|
) => {
|
|
102
119
|
await qb.transaction(
|
|
@@ -107,7 +124,7 @@ export const dropTriggers = async (
|
|
|
107
124
|
|
|
108
125
|
await tx.wrap({ label: "drop_trigger" }, (tx) =>
|
|
109
126
|
tx.execute(
|
|
110
|
-
`DROP TRIGGER IF EXISTS "${
|
|
127
|
+
`DROP TRIGGER IF EXISTS "${getReorgTriggerName()}" ON "${schema}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"`,
|
|
111
128
|
),
|
|
112
129
|
);
|
|
113
130
|
}),
|
|
@@ -118,6 +135,155 @@ export const dropTriggers = async (
|
|
|
118
135
|
);
|
|
119
136
|
};
|
|
120
137
|
|
|
138
|
+
export const createLiveQueryTriggers = async (
|
|
139
|
+
qb: QB,
|
|
140
|
+
{
|
|
141
|
+
namespaceBuild,
|
|
142
|
+
tables,
|
|
143
|
+
chainId,
|
|
144
|
+
}: { namespaceBuild: NamespaceBuild; tables: Table[]; chainId?: number },
|
|
145
|
+
context?: { logger?: Logger },
|
|
146
|
+
) => {
|
|
147
|
+
await qb.transaction(
|
|
148
|
+
async (tx) => {
|
|
149
|
+
const notifyProcedure = getLiveQueryNotifyProcedureName();
|
|
150
|
+
const notifyTrigger = getLiveQueryNotifyTriggerName();
|
|
151
|
+
|
|
152
|
+
await tx.wrap((tx) =>
|
|
153
|
+
tx.execute(
|
|
154
|
+
`
|
|
155
|
+
CREATE OR REPLACE TRIGGER "${notifyTrigger}"
|
|
156
|
+
AFTER INSERT OR UPDATE OR DELETE
|
|
157
|
+
ON "${namespaceBuild.schema}"._ponder_checkpoint
|
|
158
|
+
FOR EACH STATEMENT
|
|
159
|
+
EXECUTE PROCEDURE "${namespaceBuild.schema}".${notifyProcedure};`,
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const trigger = getLiveQueryTriggerName();
|
|
164
|
+
const procedure = getLiveQueryProcedureName();
|
|
165
|
+
|
|
166
|
+
for (const table of tables) {
|
|
167
|
+
const schema = getTableConfig(table).schema ?? "public";
|
|
168
|
+
|
|
169
|
+
await tx.wrap((tx) =>
|
|
170
|
+
tx.execute(
|
|
171
|
+
`
|
|
172
|
+
CREATE OR REPLACE TRIGGER "${trigger}"
|
|
173
|
+
AFTER INSERT OR UPDATE OR DELETE
|
|
174
|
+
ON "${schema}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}"
|
|
175
|
+
FOR EACH STATEMENT
|
|
176
|
+
EXECUTE PROCEDURE "${schema}".${procedure};`,
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
undefined,
|
|
182
|
+
context,
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const dropLiveQueryTriggers = async (
|
|
187
|
+
qb: QB,
|
|
188
|
+
{
|
|
189
|
+
namespaceBuild,
|
|
190
|
+
tables,
|
|
191
|
+
chainId,
|
|
192
|
+
}: { namespaceBuild: NamespaceBuild; tables: Table[]; chainId?: number },
|
|
193
|
+
context?: { logger?: Logger },
|
|
194
|
+
) => {
|
|
195
|
+
await qb.transaction(
|
|
196
|
+
async (tx) => {
|
|
197
|
+
const notifyTrigger = getLiveQueryNotifyTriggerName();
|
|
198
|
+
await tx.wrap((tx) =>
|
|
199
|
+
tx.execute(
|
|
200
|
+
`DROP TRIGGER IF EXISTS "${notifyTrigger}" ON "${namespaceBuild.schema}"._ponder_checkpoint;`,
|
|
201
|
+
),
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const trigger = getLiveQueryTriggerName();
|
|
205
|
+
for (const table of tables) {
|
|
206
|
+
const schema = getTableConfig(table).schema ?? "public";
|
|
207
|
+
|
|
208
|
+
await tx.wrap((tx) =>
|
|
209
|
+
tx.execute(
|
|
210
|
+
`DROP TRIGGER IF EXISTS "${trigger}" ON "${schema}"."${chainId === undefined ? getTableName(table) : getPartitionName(table, chainId)}";`,
|
|
211
|
+
),
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
undefined,
|
|
216
|
+
context,
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export const createLiveQueryProcedures = async (
|
|
221
|
+
qb: QB,
|
|
222
|
+
{ namespaceBuild }: { namespaceBuild: NamespaceBuild },
|
|
223
|
+
context?: { logger?: Logger },
|
|
224
|
+
) => {
|
|
225
|
+
await qb.transaction(
|
|
226
|
+
async (tx) => {
|
|
227
|
+
const schema = namespaceBuild.schema;
|
|
228
|
+
const procedure = getLiveQueryProcedureName();
|
|
229
|
+
|
|
230
|
+
await tx.wrap(
|
|
231
|
+
(tx) =>
|
|
232
|
+
tx.execute(
|
|
233
|
+
`
|
|
234
|
+
CREATE OR REPLACE FUNCTION "${schema}".${procedure}
|
|
235
|
+
RETURNS TRIGGER LANGUAGE plpgsql
|
|
236
|
+
AS $$
|
|
237
|
+
BEGIN
|
|
238
|
+
INSERT INTO live_query_tables (table_name)
|
|
239
|
+
VALUES (TG_TABLE_NAME)
|
|
240
|
+
ON CONFLICT (table_name) DO NOTHING;
|
|
241
|
+
RETURN NULL;
|
|
242
|
+
END;
|
|
243
|
+
$$;`,
|
|
244
|
+
),
|
|
245
|
+
context,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const notifyProcedure = getLiveQueryNotifyProcedureName();
|
|
249
|
+
const channel = getLiveQueryChannelName(namespaceBuild.schema);
|
|
250
|
+
|
|
251
|
+
await tx.wrap(
|
|
252
|
+
(tx) =>
|
|
253
|
+
tx.execute(`
|
|
254
|
+
CREATE OR REPLACE FUNCTION "${schema}".${notifyProcedure}
|
|
255
|
+
RETURNS TRIGGER LANGUAGE plpgsql
|
|
256
|
+
AS $$
|
|
257
|
+
DECLARE
|
|
258
|
+
table_names json;
|
|
259
|
+
table_exists boolean := false;
|
|
260
|
+
BEGIN
|
|
261
|
+
SELECT EXISTS (
|
|
262
|
+
SELECT 1
|
|
263
|
+
FROM information_schema.tables
|
|
264
|
+
WHERE table_name = 'live_query_tables'
|
|
265
|
+
AND table_type = 'LOCAL TEMPORARY'
|
|
266
|
+
) INTO table_exists;
|
|
267
|
+
|
|
268
|
+
IF table_exists THEN
|
|
269
|
+
SELECT json_agg(table_name) INTO table_names
|
|
270
|
+
FROM live_query_tables;
|
|
271
|
+
|
|
272
|
+
table_names := COALESCE(table_names, '[]'::json);
|
|
273
|
+
PERFORM pg_notify('${channel}', table_names::text);
|
|
274
|
+
END IF;
|
|
275
|
+
|
|
276
|
+
RETURN NULL;
|
|
277
|
+
END;
|
|
278
|
+
$$;`),
|
|
279
|
+
context,
|
|
280
|
+
);
|
|
281
|
+
},
|
|
282
|
+
undefined,
|
|
283
|
+
context,
|
|
284
|
+
);
|
|
285
|
+
};
|
|
286
|
+
|
|
121
287
|
export const createViews = async (
|
|
122
288
|
qb: QB,
|
|
123
289
|
{
|
|
@@ -191,30 +357,51 @@ export const createViews = async (
|
|
|
191
357
|
),
|
|
192
358
|
);
|
|
193
359
|
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const channel = `${namespaceBuild.viewsSchema}_status_channel`;
|
|
360
|
+
const notifyProcedure = getLiveQueryNotifyProcedureName();
|
|
361
|
+
const channel = getLiveQueryChannelName(namespaceBuild.viewsSchema!);
|
|
197
362
|
|
|
198
363
|
await tx.wrap((tx) =>
|
|
199
364
|
tx.execute(`
|
|
200
|
-
CREATE OR REPLACE FUNCTION "${namespaceBuild.viewsSchema}".${
|
|
201
|
-
RETURNS TRIGGER
|
|
202
|
-
LANGUAGE plpgsql
|
|
365
|
+
CREATE OR REPLACE FUNCTION "${namespaceBuild.viewsSchema}".${notifyProcedure}
|
|
366
|
+
RETURNS TRIGGER LANGUAGE plpgsql
|
|
203
367
|
AS $$
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
368
|
+
DECLARE
|
|
369
|
+
table_names json;
|
|
370
|
+
table_exists boolean := false;
|
|
371
|
+
BEGIN
|
|
372
|
+
SELECT EXISTS (
|
|
373
|
+
SELECT 1
|
|
374
|
+
FROM information_schema.tables
|
|
375
|
+
WHERE table_name = 'live_query_tables'
|
|
376
|
+
AND table_type = 'LOCAL TEMPORARY'
|
|
377
|
+
) INTO table_exists;
|
|
378
|
+
|
|
379
|
+
IF table_exists THEN
|
|
380
|
+
SELECT json_agg(table_name) INTO table_names
|
|
381
|
+
FROM live_query_tables;
|
|
382
|
+
|
|
383
|
+
table_names := COALESCE(table_names, '[]'::json);
|
|
384
|
+
PERFORM pg_notify('${channel}', table_names::text);
|
|
385
|
+
END IF;
|
|
386
|
+
|
|
387
|
+
RETURN NULL;
|
|
388
|
+
END;
|
|
208
389
|
$$;`),
|
|
209
390
|
);
|
|
210
391
|
|
|
392
|
+
const trigger = getViewsLiveQueryNotifyTriggerName(
|
|
393
|
+
namespaceBuild.viewsSchema,
|
|
394
|
+
);
|
|
395
|
+
|
|
211
396
|
await tx.wrap((tx) =>
|
|
212
|
-
tx.execute(
|
|
397
|
+
tx.execute(
|
|
398
|
+
`
|
|
213
399
|
CREATE OR REPLACE TRIGGER "${trigger}"
|
|
214
400
|
AFTER INSERT OR UPDATE OR DELETE
|
|
215
|
-
ON "${namespaceBuild.schema}"._ponder_checkpoint
|
|
401
|
+
ON "${namespaceBuild.schema!}"._ponder_checkpoint
|
|
216
402
|
FOR EACH STATEMENT
|
|
217
|
-
EXECUTE PROCEDURE "${namespaceBuild.viewsSchema}".${
|
|
403
|
+
EXECUTE PROCEDURE "${namespaceBuild.viewsSchema}".${notifyProcedure};`,
|
|
404
|
+
),
|
|
218
405
|
);
|
|
219
406
|
},
|
|
220
407
|
undefined,
|
|
@@ -222,16 +409,65 @@ EXECUTE PROCEDURE "${namespaceBuild.viewsSchema}".${notification};`),
|
|
|
222
409
|
);
|
|
223
410
|
};
|
|
224
411
|
|
|
225
|
-
export const
|
|
412
|
+
export const revertOmnichain = async (
|
|
413
|
+
qb: QB,
|
|
414
|
+
{
|
|
415
|
+
checkpoint,
|
|
416
|
+
tables,
|
|
417
|
+
}: {
|
|
418
|
+
checkpoint: string;
|
|
419
|
+
tables: Table[];
|
|
420
|
+
},
|
|
421
|
+
context?: { logger?: Logger },
|
|
422
|
+
): Promise<number[]> => {
|
|
423
|
+
if (tables.length === 0) return [];
|
|
424
|
+
|
|
425
|
+
return qb.transaction(
|
|
426
|
+
{ label: "revert" },
|
|
427
|
+
async (tx) => {
|
|
428
|
+
const counts: number[] = [];
|
|
429
|
+
|
|
430
|
+
for (const table of tables) {
|
|
431
|
+
const primaryKeyColumns = getPrimaryKeyColumns(table);
|
|
432
|
+
const schema = getTableConfig(table).schema ?? "public";
|
|
433
|
+
|
|
434
|
+
const result = await tx.wrap((tx) =>
|
|
435
|
+
tx.execute(`
|
|
436
|
+
WITH reverted1 AS (
|
|
437
|
+
DELETE FROM "${schema}"."${getReorgTableName(table)}"
|
|
438
|
+
WHERE checkpoint > '${checkpoint}' RETURNING *
|
|
439
|
+
), reverted2 AS (
|
|
440
|
+
SELECT ${primaryKeyColumns.map(({ sql }) => `"${sql}"`).join(", ")}, MIN(operation_id) AS operation_id FROM reverted1
|
|
441
|
+
GROUP BY ${primaryKeyColumns.map(({ sql }) => `"${sql}"`).join(", ")}
|
|
442
|
+
), reverted3 AS (
|
|
443
|
+
SELECT ${Object.values(getTableColumns(table))
|
|
444
|
+
.map((column) => `reverted1."${getColumnCasing(column, "snake_case")}"`)
|
|
445
|
+
.join(", ")}, reverted1.operation FROM reverted2
|
|
446
|
+
INNER JOIN reverted1
|
|
447
|
+
ON ${primaryKeyColumns.map(({ sql }) => `reverted2."${sql}" = reverted1."${sql}"`).join("AND ")}
|
|
448
|
+
AND reverted2.operation_id = reverted1.operation_id
|
|
449
|
+
), ${getRevertSql({ table })};`),
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
// @ts-ignore
|
|
453
|
+
counts.push(result.rows[0]!.count);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return counts;
|
|
457
|
+
},
|
|
458
|
+
undefined,
|
|
459
|
+
context,
|
|
460
|
+
);
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
export const revertMultichain = async (
|
|
226
464
|
qb: QB,
|
|
227
465
|
{
|
|
228
466
|
checkpoint,
|
|
229
467
|
tables,
|
|
230
|
-
preBuild,
|
|
231
468
|
}: {
|
|
232
469
|
checkpoint: string;
|
|
233
470
|
tables: Table[];
|
|
234
|
-
preBuild: Pick<PreBuild, "ordering">;
|
|
235
471
|
},
|
|
236
472
|
context?: { logger?: Logger },
|
|
237
473
|
): Promise<number[]> => {
|
|
@@ -241,33 +477,33 @@ export const revert = async (
|
|
|
241
477
|
{ label: "revert" },
|
|
242
478
|
async (tx) => {
|
|
243
479
|
const counts: number[] = [];
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
480
|
+
|
|
481
|
+
const minOperationId = await tx
|
|
482
|
+
.wrap((tx) =>
|
|
483
|
+
tx.execute(`
|
|
248
484
|
SELECT MIN(operation_id) AS operation_id FROM (
|
|
249
485
|
${tables
|
|
250
486
|
.map(
|
|
251
487
|
(table) => `
|
|
252
|
-
SELECT MIN(operation_id) AS operation_id FROM "${getTableConfig(table).schema ?? "public"}"."${
|
|
488
|
+
SELECT MIN(operation_id) AS operation_id FROM "${getTableConfig(table).schema ?? "public"}"."${getReorgTableName(table)}"
|
|
253
489
|
WHERE SUBSTRING(checkpoint, 11, 16)::numeric = ${String(decodeCheckpoint(checkpoint).chainId)}
|
|
254
490
|
AND checkpoint > '${checkpoint}'`,
|
|
255
491
|
)
|
|
256
492
|
.join(" UNION ALL ")}) AS all_mins;`),
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
for (const table of tables) {
|
|
264
|
-
const primaryKeyColumns = getPrimaryKeyColumns(table);
|
|
265
|
-
const schema = getTableConfig(table).schema ?? "public";
|
|
493
|
+
)
|
|
494
|
+
.then((result) => {
|
|
495
|
+
// @ts-ignore
|
|
496
|
+
return result.rows[0]?.operation_id as string | null;
|
|
497
|
+
});
|
|
266
498
|
|
|
267
|
-
|
|
268
|
-
|
|
499
|
+
for (const table of tables) {
|
|
500
|
+
const primaryKeyColumns = getPrimaryKeyColumns(table);
|
|
501
|
+
const schema = getTableConfig(table).schema ?? "public";
|
|
502
|
+
|
|
503
|
+
const result = await tx.wrap((tx) =>
|
|
504
|
+
tx.execute(`
|
|
269
505
|
WITH reverted1 AS (
|
|
270
|
-
DELETE FROM "${schema}"."${
|
|
506
|
+
DELETE FROM "${schema}"."${getReorgTableName(table)}"
|
|
271
507
|
WHERE ${minOperationId!} IS NOT NULL AND operation_id >= ${minOperationId!}
|
|
272
508
|
RETURNING *
|
|
273
509
|
), reverted2 AS (
|
|
@@ -281,21 +517,46 @@ WITH reverted1 AS (
|
|
|
281
517
|
ON ${primaryKeyColumns.map(({ sql }) => `reverted2."${sql}" = reverted1."${sql}"`).join("AND ")}
|
|
282
518
|
AND reverted2.operation_id = reverted1.operation_id
|
|
283
519
|
), ${getRevertSql({ table })};`),
|
|
284
|
-
|
|
520
|
+
);
|
|
285
521
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
522
|
+
// @ts-ignore
|
|
523
|
+
counts.push(result.rows[0]!.count);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return counts;
|
|
527
|
+
},
|
|
528
|
+
undefined,
|
|
529
|
+
context,
|
|
530
|
+
);
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
export const revertIsolated = async (
|
|
534
|
+
qb: QB,
|
|
535
|
+
{
|
|
536
|
+
checkpoint,
|
|
537
|
+
tables,
|
|
538
|
+
}: {
|
|
539
|
+
checkpoint: string;
|
|
540
|
+
tables: Table[];
|
|
541
|
+
},
|
|
542
|
+
context?: { logger?: Logger },
|
|
543
|
+
) => {
|
|
544
|
+
if (tables.length === 0) return [];
|
|
545
|
+
|
|
546
|
+
return qb.transaction(
|
|
547
|
+
{ label: "revert" },
|
|
548
|
+
async (tx) => {
|
|
549
|
+
const counts: number[] = [];
|
|
550
|
+
|
|
551
|
+
for (const table of tables) {
|
|
552
|
+
const primaryKeyColumns = getPrimaryKeyColumns(table);
|
|
553
|
+
const schema = getTableConfig(table).schema ?? "public";
|
|
293
554
|
|
|
294
|
-
|
|
295
|
-
|
|
555
|
+
const result = await tx.wrap((tx) =>
|
|
556
|
+
tx.execute(`
|
|
296
557
|
WITH reverted1 AS (
|
|
297
|
-
DELETE FROM "${schema}"."${
|
|
298
|
-
WHERE checkpoint > '${checkpoint}' RETURNING *
|
|
558
|
+
DELETE FROM "${schema}"."${getReorgTableName(table)}"
|
|
559
|
+
WHERE checkpoint > '${checkpoint}' AND SUBSTRING(checkpoint, 11, 16)::numeric = ${String(decodeCheckpoint(checkpoint).chainId)} RETURNING *
|
|
299
560
|
), reverted2 AS (
|
|
300
561
|
SELECT ${primaryKeyColumns.map(({ sql }) => `"${sql}"`).join(", ")}, MIN(operation_id) AS operation_id FROM reverted1
|
|
301
562
|
GROUP BY ${primaryKeyColumns.map(({ sql }) => `"${sql}"`).join(", ")}
|
|
@@ -307,11 +568,10 @@ WITH reverted1 AS (
|
|
|
307
568
|
ON ${primaryKeyColumns.map(({ sql }) => `reverted2."${sql}" = reverted1."${sql}"`).join("AND ")}
|
|
308
569
|
AND reverted2.operation_id = reverted1.operation_id
|
|
309
570
|
), ${getRevertSql({ table })};`),
|
|
310
|
-
|
|
571
|
+
);
|
|
311
572
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
573
|
+
// @ts-ignore
|
|
574
|
+
counts.push(result.rows[0]!.count);
|
|
315
575
|
}
|
|
316
576
|
|
|
317
577
|
return counts;
|
|
@@ -321,23 +581,22 @@ WITH reverted1 AS (
|
|
|
321
581
|
);
|
|
322
582
|
};
|
|
323
583
|
|
|
324
|
-
export const
|
|
584
|
+
export const finalizeOmnichain = async (
|
|
325
585
|
qb: QB,
|
|
326
586
|
{
|
|
327
587
|
checkpoint,
|
|
328
588
|
tables,
|
|
329
|
-
preBuild,
|
|
330
589
|
namespaceBuild,
|
|
331
590
|
}: {
|
|
332
591
|
checkpoint: string;
|
|
333
592
|
tables: Table[];
|
|
334
|
-
preBuild: Pick<PreBuild, "ordering">;
|
|
335
593
|
namespaceBuild: NamespaceBuild;
|
|
336
594
|
},
|
|
337
595
|
context?: { logger?: Logger },
|
|
338
|
-
)
|
|
596
|
+
) => {
|
|
339
597
|
const PONDER_CHECKPOINT = getPonderCheckpointTable(namespaceBuild.schema);
|
|
340
598
|
|
|
599
|
+
// TODO(kyle) is this breaking an invariant?
|
|
341
600
|
if (tables.length === 0) {
|
|
342
601
|
await qb.wrap(
|
|
343
602
|
(db) =>
|
|
@@ -349,27 +608,76 @@ export const finalize = async (
|
|
|
349
608
|
return;
|
|
350
609
|
}
|
|
351
610
|
|
|
352
|
-
// NOTE: It is invariant that PONDER_CHECKPOINT has a value for each chain.
|
|
353
|
-
|
|
354
611
|
return qb.transaction(
|
|
355
612
|
{ label: "finalize" },
|
|
356
613
|
async (tx) => {
|
|
357
|
-
|
|
614
|
+
await tx.wrap((tx) =>
|
|
615
|
+
tx.update(PONDER_CHECKPOINT).set({
|
|
616
|
+
finalizedCheckpoint: checkpoint,
|
|
617
|
+
safeCheckpoint: checkpoint,
|
|
618
|
+
}),
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
for (const table of tables) {
|
|
358
622
|
await tx.wrap((tx) =>
|
|
359
623
|
tx
|
|
360
|
-
.
|
|
361
|
-
.
|
|
362
|
-
.where(
|
|
363
|
-
eq(
|
|
364
|
-
PONDER_CHECKPOINT.chainId,
|
|
365
|
-
Number(decodeCheckpoint(checkpoint).chainId),
|
|
366
|
-
),
|
|
367
|
-
),
|
|
624
|
+
.delete(getReorgTable(table))
|
|
625
|
+
.where(lte(getReorgTable(table).checkpoint, checkpoint)),
|
|
368
626
|
);
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
undefined,
|
|
630
|
+
context,
|
|
631
|
+
);
|
|
632
|
+
};
|
|
369
633
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
634
|
+
export const finalizeMultichain = async (
|
|
635
|
+
qb: QB,
|
|
636
|
+
{
|
|
637
|
+
checkpoint,
|
|
638
|
+
tables,
|
|
639
|
+
namespaceBuild,
|
|
640
|
+
}: {
|
|
641
|
+
checkpoint: string;
|
|
642
|
+
tables: Table[];
|
|
643
|
+
namespaceBuild: NamespaceBuild;
|
|
644
|
+
},
|
|
645
|
+
context?: { logger?: Logger },
|
|
646
|
+
) => {
|
|
647
|
+
const PONDER_CHECKPOINT = getPonderCheckpointTable(namespaceBuild.schema);
|
|
648
|
+
|
|
649
|
+
// TODO(kyle) is this breaking an invariant?
|
|
650
|
+
if (tables.length === 0) {
|
|
651
|
+
await qb.wrap(
|
|
652
|
+
(db) =>
|
|
653
|
+
db
|
|
654
|
+
.update(PONDER_CHECKPOINT)
|
|
655
|
+
.set({ finalizedCheckpoint: checkpoint, safeCheckpoint: checkpoint }),
|
|
656
|
+
context,
|
|
657
|
+
);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// NOTE: It is invariant that PONDER_CHECKPOINT has a value for each chain.
|
|
662
|
+
|
|
663
|
+
return qb.transaction(
|
|
664
|
+
{ label: "finalize" },
|
|
665
|
+
async (tx) => {
|
|
666
|
+
await tx.wrap((tx) =>
|
|
667
|
+
tx
|
|
668
|
+
.update(PONDER_CHECKPOINT)
|
|
669
|
+
.set({ finalizedCheckpoint: checkpoint })
|
|
670
|
+
.where(
|
|
671
|
+
eq(
|
|
672
|
+
PONDER_CHECKPOINT.chainId,
|
|
673
|
+
Number(decodeCheckpoint(checkpoint).chainId),
|
|
674
|
+
),
|
|
675
|
+
),
|
|
676
|
+
);
|
|
677
|
+
|
|
678
|
+
const minOperationId = await tx
|
|
679
|
+
.wrap((tx) =>
|
|
680
|
+
tx.execute(`
|
|
373
681
|
SELECT MIN(operation_id) AS operation_id FROM (
|
|
374
682
|
${tables
|
|
375
683
|
.map(
|
|
@@ -382,14 +690,14 @@ WHERE checkpoint > (
|
|
|
382
690
|
)`,
|
|
383
691
|
)
|
|
384
692
|
.join(" UNION ALL ")}) AS all_mins;`),
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
693
|
+
)
|
|
694
|
+
.then((result) => {
|
|
695
|
+
// @ts-ignore
|
|
696
|
+
return result.rows[0]?.operation_id as string | null;
|
|
697
|
+
});
|
|
390
698
|
|
|
391
|
-
|
|
392
|
-
|
|
699
|
+
const result = await tx.wrap((tx) =>
|
|
700
|
+
tx.execute(`
|
|
393
701
|
WITH ${tables
|
|
394
702
|
.map(
|
|
395
703
|
(table, index) => `
|
|
@@ -405,39 +713,18 @@ WHERE checkpoint > (
|
|
|
405
713
|
.map((_, index) => `SELECT checkpoint FROM deleted_${index}`)
|
|
406
714
|
.join(" UNION ALL ")}
|
|
407
715
|
)
|
|
408
|
-
SELECT MAX(checkpoint) as safe_checkpoint, SUBSTRING(checkpoint, 11, 16)::numeric as chain_id
|
|
716
|
+
SELECT MAX(checkpoint) as safe_checkpoint, SUBSTRING(checkpoint, 11, 16)::numeric as chain_id
|
|
409
717
|
FROM all_deleted
|
|
410
718
|
GROUP BY SUBSTRING(checkpoint, 11, 16)::numeric;`),
|
|
411
|
-
|
|
719
|
+
);
|
|
412
720
|
|
|
413
|
-
|
|
414
|
-
await tx.wrap((tx) =>
|
|
415
|
-
tx
|
|
416
|
-
.update(PONDER_CHECKPOINT)
|
|
417
|
-
.set({ safeCheckpoint: safe_checkpoint as string })
|
|
418
|
-
.where(eq(PONDER_CHECKPOINT.chainId, chain_id as number)),
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
} else {
|
|
721
|
+
for (const { chain_id, safe_checkpoint } of result.rows) {
|
|
422
722
|
await tx.wrap((tx) =>
|
|
423
|
-
tx
|
|
424
|
-
|
|
425
|
-
safeCheckpoint:
|
|
426
|
-
|
|
723
|
+
tx
|
|
724
|
+
.update(PONDER_CHECKPOINT)
|
|
725
|
+
.set({ safeCheckpoint: safe_checkpoint as string })
|
|
726
|
+
.where(eq(PONDER_CHECKPOINT.chainId, chain_id as number)),
|
|
427
727
|
);
|
|
428
|
-
|
|
429
|
-
for (const table of tables) {
|
|
430
|
-
await tx
|
|
431
|
-
.wrap((tx) =>
|
|
432
|
-
tx.execute(`
|
|
433
|
-
WITH deleted AS (
|
|
434
|
-
DELETE FROM "${getTableConfig(table).schema ?? "public"}"."${getTableName(getReorgTable(table))}"
|
|
435
|
-
WHERE checkpoint <= '${checkpoint}'
|
|
436
|
-
RETURNING *
|
|
437
|
-
) SELECT COUNT(*) AS deleted_count FROM deleted;`),
|
|
438
|
-
)
|
|
439
|
-
.then((result) => Number(result.rows[0]!.deleted_count));
|
|
440
|
-
}
|
|
441
728
|
}
|
|
442
729
|
},
|
|
443
730
|
undefined,
|
|
@@ -445,19 +732,81 @@ WITH deleted AS (
|
|
|
445
732
|
);
|
|
446
733
|
};
|
|
447
734
|
|
|
735
|
+
export const finalizeIsolated = async (
|
|
736
|
+
qb: QB,
|
|
737
|
+
{
|
|
738
|
+
checkpoint,
|
|
739
|
+
tables,
|
|
740
|
+
namespaceBuild,
|
|
741
|
+
}: {
|
|
742
|
+
checkpoint: string;
|
|
743
|
+
tables: Table[];
|
|
744
|
+
namespaceBuild: NamespaceBuild;
|
|
745
|
+
},
|
|
746
|
+
context?: { logger?: Logger },
|
|
747
|
+
) => {
|
|
748
|
+
const PONDER_CHECKPOINT = getPonderCheckpointTable(namespaceBuild.schema);
|
|
749
|
+
const chainId = Number(decodeCheckpoint(checkpoint).chainId);
|
|
750
|
+
|
|
751
|
+
if (tables.length === 0) {
|
|
752
|
+
await qb.wrap(
|
|
753
|
+
(db) =>
|
|
754
|
+
db
|
|
755
|
+
.update(PONDER_CHECKPOINT)
|
|
756
|
+
.set({ finalizedCheckpoint: checkpoint, safeCheckpoint: checkpoint })
|
|
757
|
+
.where(eq(PONDER_CHECKPOINT.chainId, chainId)),
|
|
758
|
+
context,
|
|
759
|
+
);
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
return qb.transaction({ label: "finalize" }, async (tx) => {
|
|
763
|
+
await tx.wrap((tx) =>
|
|
764
|
+
tx
|
|
765
|
+
.update(PONDER_CHECKPOINT)
|
|
766
|
+
.set({ finalizedCheckpoint: checkpoint, safeCheckpoint: checkpoint })
|
|
767
|
+
.where(eq(PONDER_CHECKPOINT.chainId, chainId)),
|
|
768
|
+
);
|
|
769
|
+
|
|
770
|
+
for (const table of tables) {
|
|
771
|
+
await tx.wrap((tx) =>
|
|
772
|
+
tx
|
|
773
|
+
.delete(getReorgTable(table))
|
|
774
|
+
.where(
|
|
775
|
+
and(
|
|
776
|
+
lte(getReorgTable(table).checkpoint, checkpoint),
|
|
777
|
+
eq(sql`chain_id`, chainId),
|
|
778
|
+
),
|
|
779
|
+
),
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
};
|
|
784
|
+
|
|
448
785
|
export const commitBlock = async (
|
|
449
786
|
qb: QB,
|
|
450
|
-
{
|
|
787
|
+
{
|
|
788
|
+
checkpoint,
|
|
789
|
+
table,
|
|
790
|
+
preBuild,
|
|
791
|
+
}: { checkpoint: string; table: Table; preBuild: Pick<PreBuild, "ordering"> },
|
|
451
792
|
context?: { logger?: Logger },
|
|
452
793
|
) => {
|
|
453
794
|
const reorgTable = getReorgTable(table);
|
|
795
|
+
let whereClause: SQL;
|
|
796
|
+
if (preBuild.ordering === "experimental_isolated") {
|
|
797
|
+
// Note: Query must include `chain_id` because it's possible for multiple chains to be indexing in parallel.
|
|
798
|
+
const chainId = Number(decodeCheckpoint(checkpoint).chainId);
|
|
799
|
+
whereClause = and(
|
|
800
|
+
eq(reorgTable.checkpoint, MAX_CHECKPOINT_STRING),
|
|
801
|
+
eq(sql`chain_id`, chainId),
|
|
802
|
+
)!;
|
|
803
|
+
} else {
|
|
804
|
+
whereClause = eq(reorgTable.checkpoint, MAX_CHECKPOINT_STRING);
|
|
805
|
+
}
|
|
806
|
+
|
|
454
807
|
await qb.wrap(
|
|
455
808
|
{ label: "commit_block" },
|
|
456
|
-
(db) =>
|
|
457
|
-
db
|
|
458
|
-
.update(reorgTable)
|
|
459
|
-
.set({ checkpoint })
|
|
460
|
-
.where(eq(reorgTable.checkpoint, MAX_CHECKPOINT_STRING)),
|
|
809
|
+
(db) => db.update(reorgTable).set({ checkpoint }).where(whereClause),
|
|
461
810
|
context,
|
|
462
811
|
);
|
|
463
812
|
};
|