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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abi.d.ts","sourceRoot":"","sources":["../../../src/utils/abi.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,QAAQ,EACb,KAAK,WAAW,EAEjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAEL,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"abi.d.ts","sourceRoot":"","sources":["../../../src/utils/abi.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,QAAQ,EACb,KAAK,WAAW,EAEjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAEL,KAAK,GAAG,EAIT,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAgB;QACxB,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;KACnE;CACF;AAED,eAAO,MAAM,UAAU;;UAGF,QAAQ,GAAG,WAAW;YA8B1C,CAAC;AAEF,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,GACzD;IACD,MAAM,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;CAC5B,EAAE,CAmBF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk.d.ts","sourceRoot":"","sources":["../../../src/utils/chunk.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,wBAAyB,MAAM,UAMhD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Like `Promise.allSettled` but throws if any of the promises reject.
|
|
3
|
+
*
|
|
4
|
+
* @dev This is very useful when dealing with multiple concurrent promises
|
|
5
|
+
* in a database transaction.
|
|
6
|
+
*/
|
|
7
|
+
export declare function promiseAllSettledWithThrow<T>(promises: Promise<T>[]): Promise<T[]>;
|
|
8
|
+
//# sourceMappingURL=promiseAllSettledWithThrow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promiseAllSettledWithThrow.d.ts","sourceRoot":"","sources":["../../../src/utils/promiseAllSettledWithThrow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAAC,CAAC,EAChD,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GACrB,OAAO,CAAC,CAAC,EAAE,CAAC,CAkBd"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Node } from "@pgsql/types";
|
|
2
|
+
export declare const parseSQLQuery: (sql: string) => Promise<Node>;
|
|
3
|
+
/**
|
|
4
|
+
* Validate a SQL query.
|
|
5
|
+
*
|
|
6
|
+
* @param sql - SQL query
|
|
7
|
+
*/
|
|
8
|
+
export declare const validateAllowableSQLQuery: (sql: string) => Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Return `true` if the SQL query is readonly, else `false`.
|
|
11
|
+
*
|
|
12
|
+
* @param sql - SQL query
|
|
13
|
+
*/
|
|
14
|
+
export declare const isReadonlySQLQuery: (sql: string) => Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Find all referenced relations in a SQL query.
|
|
17
|
+
*
|
|
18
|
+
* @param sql - SQL query
|
|
19
|
+
*/
|
|
20
|
+
export declare const getSQLQueryRelations: (sql: string) => Promise<Set<string>>;
|
|
21
|
+
//# sourceMappingURL=sql-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-parse.d.ts","sourceRoot":"","sources":["../../../src/utils/sql-parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAe5D,eAAO,MAAM,aAAa,QAAe,MAAM,KAAG,QAAQ,IAAI,CAiC7D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAe,MAAM,kBAuD1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAe,MAAM,KAAG,QAAQ,OAAO,CA2BrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAC1B,MAAM,KACV,QAAQ,IAAI,MAAM,CAAC,CAoDrB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ponder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "An open-source framework for crypto application backends",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"rimraf": "^5.0.5",
|
|
100
100
|
"tsx": "^4.19.2",
|
|
101
101
|
"vitest": "^1.0.2",
|
|
102
|
-
"@ponder/client": "0.
|
|
102
|
+
"@ponder/client": "0.15.0"
|
|
103
103
|
},
|
|
104
104
|
"engines": {
|
|
105
105
|
"node": ">=18.14"
|
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
createDatabase,
|
|
11
11
|
getPonderMetaTable,
|
|
12
12
|
} from "@/database/index.js";
|
|
13
|
+
import {
|
|
14
|
+
getLiveQueryChannelName,
|
|
15
|
+
getLiveQueryNotifyProcedureName,
|
|
16
|
+
getViewsLiveQueryNotifyTriggerName,
|
|
17
|
+
} from "@/drizzle/onchain.js";
|
|
13
18
|
import { sql } from "@/index.js";
|
|
14
19
|
import { createLogger } from "@/internal/logger.js";
|
|
15
20
|
import { MetricsService } from "@/internal/metrics.js";
|
|
@@ -257,25 +262,40 @@ export async function createViews({
|
|
|
257
262
|
),
|
|
258
263
|
);
|
|
259
264
|
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
const channel = `${cliOptions.viewsSchema}_status_channel`;
|
|
265
|
+
const notifyProcedure = getLiveQueryNotifyProcedureName();
|
|
266
|
+
const channel = getLiveQueryChannelName(cliOptions.viewsSchema);
|
|
263
267
|
|
|
264
268
|
await database.adminQB.wrap((db) =>
|
|
265
|
-
db.execute(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
RETURNS TRIGGER
|
|
269
|
-
LANGUAGE plpgsql
|
|
269
|
+
db.execute(`
|
|
270
|
+
CREATE OR REPLACE FUNCTION "${cliOptions.viewsSchema}".${notifyProcedure}
|
|
271
|
+
RETURNS TRIGGER LANGUAGE plpgsql
|
|
270
272
|
AS $$
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
DECLARE
|
|
274
|
+
table_names json;
|
|
275
|
+
table_exists boolean := false;
|
|
276
|
+
BEGIN
|
|
277
|
+
SELECT EXISTS (
|
|
278
|
+
SELECT 1
|
|
279
|
+
FROM information_schema.tables
|
|
280
|
+
WHERE table_name = 'live_query_tables'
|
|
281
|
+
AND table_type = 'LOCAL TEMPORARY'
|
|
282
|
+
) INTO table_exists;
|
|
283
|
+
|
|
284
|
+
IF table_exists THEN
|
|
285
|
+
SELECT json_agg(table_name) INTO table_names
|
|
286
|
+
FROM live_query_tables;
|
|
287
|
+
|
|
288
|
+
table_names := COALESCE(table_names, '[]'::json);
|
|
289
|
+
PERFORM pg_notify('${channel}', table_names::text);
|
|
290
|
+
END IF;
|
|
291
|
+
|
|
292
|
+
RETURN NULL;
|
|
293
|
+
END;
|
|
294
|
+
$$;`),
|
|
277
295
|
);
|
|
278
296
|
|
|
297
|
+
const trigger = getViewsLiveQueryNotifyTriggerName(cliOptions.viewsSchema);
|
|
298
|
+
|
|
279
299
|
await database.adminQB.wrap((db) =>
|
|
280
300
|
db.execute(
|
|
281
301
|
`
|
|
@@ -283,7 +303,7 @@ CREATE OR REPLACE TRIGGER "${trigger}"
|
|
|
283
303
|
AFTER INSERT OR UPDATE OR DELETE
|
|
284
304
|
ON "${cliOptions.schema!}"._ponder_checkpoint
|
|
285
305
|
FOR EACH STATEMENT
|
|
286
|
-
EXECUTE PROCEDURE "${cliOptions.viewsSchema}".${
|
|
306
|
+
EXECUTE PROCEDURE "${cliOptions.viewsSchema}".${notifyProcedure};`,
|
|
287
307
|
),
|
|
288
308
|
);
|
|
289
309
|
|
package/src/bin/commands/dev.ts
CHANGED
|
@@ -19,7 +19,9 @@ import { createServer } from "@/server/index.js";
|
|
|
19
19
|
import { createUi } from "@/ui/index.js";
|
|
20
20
|
import { createQueue } from "@/utils/queue.js";
|
|
21
21
|
import type { Result } from "@/utils/result.js";
|
|
22
|
+
import { isolatedController } from "../isolatedController.js";
|
|
22
23
|
import type { CliOptions } from "../ponder.js";
|
|
24
|
+
import { runCodegen } from "../utils/codegen.js";
|
|
23
25
|
import { createExit } from "../utils/exit.js";
|
|
24
26
|
|
|
25
27
|
export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
|
|
@@ -73,6 +75,8 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
|
|
|
73
75
|
);
|
|
74
76
|
}
|
|
75
77
|
|
|
78
|
+
runCodegen({ common });
|
|
79
|
+
|
|
76
80
|
const build = await createBuild({ common, cliOptions });
|
|
77
81
|
|
|
78
82
|
if (cliOptions.disableUi !== true) {
|
|
@@ -174,7 +178,10 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
|
|
|
174
178
|
return;
|
|
175
179
|
}
|
|
176
180
|
|
|
177
|
-
const compileSchemaResult = build.compileSchema(
|
|
181
|
+
const compileSchemaResult = build.compileSchema({
|
|
182
|
+
...schemaResult.result,
|
|
183
|
+
preBuild: preCompileResult.result,
|
|
184
|
+
});
|
|
178
185
|
|
|
179
186
|
if (compileSchemaResult.status === "error") {
|
|
180
187
|
common.logger.error({
|
|
@@ -344,26 +351,41 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
|
|
|
344
351
|
schemaBuild: compileSchemaResult.result,
|
|
345
352
|
});
|
|
346
353
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
354
|
+
switch (preCompileResult.result.ordering) {
|
|
355
|
+
case "omnichain":
|
|
356
|
+
runOmnichain({
|
|
357
|
+
common,
|
|
358
|
+
database,
|
|
359
|
+
preBuild: preCompileResult.result,
|
|
360
|
+
namespaceBuild: { schema, viewsSchema: undefined },
|
|
361
|
+
schemaBuild: compileSchemaResult.result,
|
|
362
|
+
indexingBuild: indexingBuildResult.result,
|
|
363
|
+
crashRecoveryCheckpoint,
|
|
364
|
+
});
|
|
365
|
+
break;
|
|
366
|
+
case "multichain":
|
|
367
|
+
runMultichain({
|
|
368
|
+
common,
|
|
369
|
+
database,
|
|
370
|
+
preBuild: preCompileResult.result,
|
|
371
|
+
namespaceBuild: { schema, viewsSchema: undefined },
|
|
372
|
+
schemaBuild: compileSchemaResult.result,
|
|
373
|
+
indexingBuild: indexingBuildResult.result,
|
|
374
|
+
crashRecoveryCheckpoint,
|
|
375
|
+
});
|
|
376
|
+
break;
|
|
377
|
+
case "experimental_isolated": {
|
|
378
|
+
isolatedController({
|
|
379
|
+
common,
|
|
380
|
+
database,
|
|
381
|
+
preBuild: preCompileResult.result,
|
|
382
|
+
namespaceBuild: { schema, viewsSchema: undefined },
|
|
383
|
+
schemaBuild: compileSchemaResult.result,
|
|
384
|
+
indexingBuild: indexingBuildResult.result,
|
|
385
|
+
crashRecoveryCheckpoint,
|
|
386
|
+
});
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
367
389
|
}
|
|
368
390
|
} else {
|
|
369
391
|
metrics.resetApiMetrics();
|
|
@@ -12,6 +12,10 @@ import {
|
|
|
12
12
|
} from "@/database/index.js";
|
|
13
13
|
import { TABLES } from "@/database/index.js";
|
|
14
14
|
import { sqlToReorgTableName } from "@/drizzle/kit/index.js";
|
|
15
|
+
import {
|
|
16
|
+
getLiveQueryNotifyProcedureName,
|
|
17
|
+
getLiveQueryProcedureName,
|
|
18
|
+
} from "@/drizzle/onchain.js";
|
|
15
19
|
import { createLogger } from "@/internal/logger.js";
|
|
16
20
|
import { MetricsService } from "@/internal/metrics.js";
|
|
17
21
|
import { buildOptions } from "@/internal/options.js";
|
|
@@ -215,6 +219,8 @@ export async function prune({ cliOptions }: { cliOptions: CliOptions }) {
|
|
|
215
219
|
tablesToDrop.push(`"${schema}"."${sqlToReorgTableName(table)}"`);
|
|
216
220
|
functionsToDrop.push(`"${schema}"."operation_reorg__${table}"`);
|
|
217
221
|
}
|
|
222
|
+
functionsToDrop.push(`"${schema}".${getLiveQueryProcedureName()}`);
|
|
223
|
+
functionsToDrop.push(`"${schema}".${getLiveQueryNotifyProcedureName()}`);
|
|
218
224
|
if ("view_names" in value) {
|
|
219
225
|
for (const view of value.view_names) {
|
|
220
226
|
viewsToDrop.push(`"${schema}"."${view}"`);
|
|
@@ -126,7 +126,10 @@ export async function serve({ cliOptions }: { cliOptions: CliOptions }) {
|
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
const compileSchemaResult = build.compileSchema(
|
|
129
|
+
const compileSchemaResult = build.compileSchema({
|
|
130
|
+
...schemaResult.result,
|
|
131
|
+
preBuild: preCompileResult.result,
|
|
132
|
+
});
|
|
130
133
|
|
|
131
134
|
if (compileSchemaResult.status === "error") {
|
|
132
135
|
common.logger.error({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runCodegen } from "@/bin/utils/codegen.js";
|
|
1
2
|
import { createBuild } from "@/build/index.js";
|
|
2
3
|
import { type Database, createDatabase } from "@/database/index.js";
|
|
3
4
|
import type { Common } from "@/internal/common.js";
|
|
@@ -17,6 +18,7 @@ import type {
|
|
|
17
18
|
import { runMultichain } from "@/runtime/multichain.js";
|
|
18
19
|
import { runOmnichain } from "@/runtime/omnichain.js";
|
|
19
20
|
import { createServer } from "@/server/index.js";
|
|
21
|
+
import { isolatedController } from "../isolatedController.js";
|
|
20
22
|
import type { CliOptions } from "../ponder.js";
|
|
21
23
|
import { createExit } from "../utils/exit.js";
|
|
22
24
|
|
|
@@ -83,6 +85,8 @@ export async function start({
|
|
|
83
85
|
);
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
runCodegen({ common });
|
|
89
|
+
|
|
86
90
|
const build = await createBuild({ common, cliOptions });
|
|
87
91
|
|
|
88
92
|
// biome-ignore lint/style/useConst: <explanation>
|
|
@@ -146,7 +150,10 @@ export async function start({
|
|
|
146
150
|
return;
|
|
147
151
|
}
|
|
148
152
|
|
|
149
|
-
const compileSchemaResult = build.compileSchema(
|
|
153
|
+
const compileSchemaResult = build.compileSchema({
|
|
154
|
+
...schemaResult.result,
|
|
155
|
+
preBuild: preCompileResult.result,
|
|
156
|
+
});
|
|
150
157
|
|
|
151
158
|
if (compileSchemaResult.status === "error") {
|
|
152
159
|
common.logger.error({
|
|
@@ -292,11 +299,19 @@ export async function start({
|
|
|
292
299
|
|
|
293
300
|
metrics.initializeIndexingMetrics(app);
|
|
294
301
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
302
|
+
switch (preCompileResult.result.ordering) {
|
|
303
|
+
case "omnichain":
|
|
304
|
+
runOmnichain(app);
|
|
305
|
+
break;
|
|
306
|
+
case "multichain":
|
|
307
|
+
runMultichain(app);
|
|
308
|
+
break;
|
|
309
|
+
case "experimental_isolated": {
|
|
310
|
+
isolatedController(app);
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
299
313
|
}
|
|
314
|
+
|
|
300
315
|
createServer(app);
|
|
301
316
|
|
|
302
317
|
return shutdown.kill;
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import url from "node:url";
|
|
3
|
+
import v8 from "node:v8";
|
|
4
|
+
import { Worker } from "node:worker_threads";
|
|
5
|
+
import { createIndexes, createViews } from "@/database/actions.js";
|
|
6
|
+
import { type Database, getPonderMetaTable } from "@/database/index.js";
|
|
7
|
+
import type { Common } from "@/internal/common.js";
|
|
8
|
+
import {
|
|
9
|
+
NonRetryableUserError,
|
|
10
|
+
nonRetryableUserErrorNames,
|
|
11
|
+
} from "@/internal/errors.js";
|
|
12
|
+
import { AggregateMetricsService, getAppProgress } from "@/internal/metrics.js";
|
|
13
|
+
import type {
|
|
14
|
+
CrashRecoveryCheckpoint,
|
|
15
|
+
IndexingBuild,
|
|
16
|
+
NamespaceBuild,
|
|
17
|
+
PreBuild,
|
|
18
|
+
SchemaBuild,
|
|
19
|
+
} from "@/internal/types.js";
|
|
20
|
+
import { runIsolated } from "@/runtime/isolated.js";
|
|
21
|
+
import { chunk } from "@/utils/chunk.js";
|
|
22
|
+
import { formatEta, formatPercentage } from "@/utils/format.js";
|
|
23
|
+
import { startClock } from "@/utils/timer.js";
|
|
24
|
+
import { isTable, isView, sql } from "drizzle-orm";
|
|
25
|
+
import type { isolatedWorker } from "./isolatedWorker.js";
|
|
26
|
+
|
|
27
|
+
const __filename = url.fileURLToPath(import.meta.url);
|
|
28
|
+
const __dirname = path.dirname(__filename);
|
|
29
|
+
|
|
30
|
+
type WorkerState = "backfill" | "live" | "complete";
|
|
31
|
+
|
|
32
|
+
export async function isolatedController({
|
|
33
|
+
common,
|
|
34
|
+
preBuild,
|
|
35
|
+
namespaceBuild,
|
|
36
|
+
schemaBuild,
|
|
37
|
+
indexingBuild,
|
|
38
|
+
crashRecoveryCheckpoint,
|
|
39
|
+
database,
|
|
40
|
+
}: {
|
|
41
|
+
common: Common;
|
|
42
|
+
preBuild: PreBuild;
|
|
43
|
+
namespaceBuild: NamespaceBuild;
|
|
44
|
+
schemaBuild: SchemaBuild;
|
|
45
|
+
indexingBuild: IndexingBuild;
|
|
46
|
+
crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
|
|
47
|
+
database: Database;
|
|
48
|
+
}) {
|
|
49
|
+
const backfillEndClock = startClock();
|
|
50
|
+
const perChainState = new Map<number, WorkerState>();
|
|
51
|
+
|
|
52
|
+
const etaInterval = setInterval(async () => {
|
|
53
|
+
const { eta, progress } = await getAppProgress(common.metrics);
|
|
54
|
+
|
|
55
|
+
if (eta === undefined && progress === undefined) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
common.logger.info({
|
|
60
|
+
msg: "Updated backfill indexing progress",
|
|
61
|
+
progress: progress === undefined ? undefined : formatPercentage(progress),
|
|
62
|
+
estimate: eta === undefined ? undefined : formatEta(eta * 1_000),
|
|
63
|
+
});
|
|
64
|
+
}, 5_000);
|
|
65
|
+
|
|
66
|
+
common.shutdown.add(() => {
|
|
67
|
+
clearInterval(etaInterval);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
let isAllReady = false;
|
|
71
|
+
let isAllComplete = false;
|
|
72
|
+
const callback = async () => {
|
|
73
|
+
if (
|
|
74
|
+
isAllReady === false &&
|
|
75
|
+
indexingBuild.chains.every(
|
|
76
|
+
(chain) => perChainState.get(chain.id) !== "backfill",
|
|
77
|
+
)
|
|
78
|
+
) {
|
|
79
|
+
isAllReady = true;
|
|
80
|
+
|
|
81
|
+
common.logger.info({
|
|
82
|
+
msg: "Completed backfill indexing across all chains",
|
|
83
|
+
duration: backfillEndClock(),
|
|
84
|
+
});
|
|
85
|
+
clearInterval(etaInterval);
|
|
86
|
+
|
|
87
|
+
let endClock = startClock();
|
|
88
|
+
await createIndexes(database.adminQB, {
|
|
89
|
+
statements: schemaBuild.statements,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (schemaBuild.statements.indexes.sql.length > 0) {
|
|
93
|
+
common.logger.info({
|
|
94
|
+
msg: "Created database indexes",
|
|
95
|
+
count: schemaBuild.statements.indexes.sql.length,
|
|
96
|
+
duration: endClock(),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (namespaceBuild.viewsSchema !== undefined) {
|
|
101
|
+
endClock = startClock();
|
|
102
|
+
|
|
103
|
+
const tables = Object.values(schemaBuild.schema).filter(isTable);
|
|
104
|
+
const views = Object.values(schemaBuild.schema).filter(isView);
|
|
105
|
+
await createViews(database.adminQB, { tables, views, namespaceBuild });
|
|
106
|
+
|
|
107
|
+
common.logger.info({
|
|
108
|
+
msg: "Created database views",
|
|
109
|
+
schema: namespaceBuild.viewsSchema,
|
|
110
|
+
count: tables.length,
|
|
111
|
+
duration: endClock(),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
endClock = startClock();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
await database.adminQB.wrap({ label: "update_ready" }, (db) =>
|
|
118
|
+
db
|
|
119
|
+
.update(getPonderMetaTable(namespaceBuild.schema))
|
|
120
|
+
.set({ value: sql`jsonb_set(value, '{is_ready}', to_jsonb(1))` }),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
common.logger.info({
|
|
124
|
+
msg: "Started returning 200 responses",
|
|
125
|
+
endpoint: "/ready",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (
|
|
130
|
+
isAllComplete === false &&
|
|
131
|
+
indexingBuild.chains.every(
|
|
132
|
+
(chain) => perChainState.get(chain.id) === "complete",
|
|
133
|
+
)
|
|
134
|
+
) {
|
|
135
|
+
isAllComplete = true;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
common.options.command === "dev" ||
|
|
141
|
+
indexingBuild.chains.length === 1 ||
|
|
142
|
+
database.driver.dialect === "pglite" ||
|
|
143
|
+
common.options.maxThreads === 1
|
|
144
|
+
) {
|
|
145
|
+
common.options.indexingCacheMaxBytes = Math.floor(
|
|
146
|
+
common.options.indexingCacheMaxBytes / indexingBuild.chains.length,
|
|
147
|
+
);
|
|
148
|
+
common.options.rpcMaxConcurrency = Math.floor(
|
|
149
|
+
common.options.rpcMaxConcurrency / indexingBuild.chains.length,
|
|
150
|
+
);
|
|
151
|
+
common.options.syncEventsQuerySize = Math.floor(
|
|
152
|
+
common.options.syncEventsQuerySize / indexingBuild.chains.length,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
await Promise.all(
|
|
156
|
+
indexingBuild.chains.map(async (chain) => {
|
|
157
|
+
const chainIndex = indexingBuild.chains.findIndex(
|
|
158
|
+
(c) => c.id === chain.id,
|
|
159
|
+
);
|
|
160
|
+
const _indexingBuild = {
|
|
161
|
+
...indexingBuild,
|
|
162
|
+
chains: [indexingBuild.chains[chainIndex]!],
|
|
163
|
+
rpcs: [indexingBuild.rpcs[chainIndex]!],
|
|
164
|
+
finalizedBlocks: [indexingBuild.finalizedBlocks[chainIndex]!],
|
|
165
|
+
eventCallbacks: [indexingBuild.eventCallbacks[chainIndex]!],
|
|
166
|
+
setupCallbacks: [indexingBuild.setupCallbacks[chainIndex]!],
|
|
167
|
+
contracts: [indexingBuild.contracts[chainIndex]!],
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
perChainState.set(chain.id, "backfill");
|
|
171
|
+
|
|
172
|
+
await runIsolated({
|
|
173
|
+
common,
|
|
174
|
+
preBuild,
|
|
175
|
+
namespaceBuild,
|
|
176
|
+
schemaBuild,
|
|
177
|
+
indexingBuild: _indexingBuild,
|
|
178
|
+
crashRecoveryCheckpoint,
|
|
179
|
+
database,
|
|
180
|
+
onReady: () => {
|
|
181
|
+
perChainState.set(chain.id, "live");
|
|
182
|
+
callback();
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
perChainState.set(chain.id, "complete");
|
|
187
|
+
callback();
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
} else {
|
|
191
|
+
const workerPath = path.join(__dirname, "isolatedWorker.js");
|
|
192
|
+
|
|
193
|
+
const perThreadChains = chunk(
|
|
194
|
+
indexingBuild.chains,
|
|
195
|
+
Math.ceil(indexingBuild.chains.length / common.options.maxThreads),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const perThreadWorkers: Worker[] = [];
|
|
199
|
+
for (const chains of perThreadChains) {
|
|
200
|
+
const chainIds = chains.map((chain) => chain.id);
|
|
201
|
+
|
|
202
|
+
// Note: This is a hack to force color support in the worker threads
|
|
203
|
+
if (process.stdout.isTTY) {
|
|
204
|
+
process.env.FORCE_COLOR = "1";
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const heapSizeLimit = v8.getHeapStatistics().heap_size_limit;
|
|
208
|
+
const perThreadHeapSizeLimit = Math.floor(
|
|
209
|
+
heapSizeLimit / (common.options.maxThreads + 1) / 1024 / 1024,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// Note: This sets `--max-old-space-size` for the worker thread.
|
|
213
|
+
// `resourceLimits` does not work because it gets overridden by
|
|
214
|
+
// CLI flags or environment variables. It does not change the heap
|
|
215
|
+
// size limit for the current main thread
|
|
216
|
+
v8.setFlagsFromString(`--max-old-space-size=${perThreadHeapSizeLimit}`);
|
|
217
|
+
|
|
218
|
+
const worker = new Worker(workerPath, {
|
|
219
|
+
workerData: {
|
|
220
|
+
options: common.options,
|
|
221
|
+
chainIds,
|
|
222
|
+
namespaceBuild,
|
|
223
|
+
crashRecoveryCheckpoint,
|
|
224
|
+
} satisfies Parameters<typeof isolatedWorker>[0],
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
for (const chainId of chainIds) {
|
|
228
|
+
perChainState.set(chainId, "backfill");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
worker.on(
|
|
232
|
+
"message",
|
|
233
|
+
(
|
|
234
|
+
message:
|
|
235
|
+
| { type: "ready"; chainId: number }
|
|
236
|
+
| { type: "done"; chainId: number }
|
|
237
|
+
| { type: "error"; error: Error },
|
|
238
|
+
) => {
|
|
239
|
+
switch (message.type) {
|
|
240
|
+
case "ready": {
|
|
241
|
+
perChainState.set(message.chainId, "live");
|
|
242
|
+
callback();
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case "done": {
|
|
246
|
+
perChainState.set(message.chainId, "complete");
|
|
247
|
+
callback();
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
case "error": {
|
|
251
|
+
let error: Error;
|
|
252
|
+
if (nonRetryableUserErrorNames.includes(message.error.name)) {
|
|
253
|
+
error = new NonRetryableUserError(message.error.message);
|
|
254
|
+
} else {
|
|
255
|
+
error = new Error(message.error.message);
|
|
256
|
+
}
|
|
257
|
+
error.name = message.error.name;
|
|
258
|
+
error.stack = message.error.stack;
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
worker.on("error", (error: Error) => {
|
|
266
|
+
if (nonRetryableUserErrorNames.includes(error.name)) {
|
|
267
|
+
error = new NonRetryableUserError(error.message);
|
|
268
|
+
} else {
|
|
269
|
+
error = new Error(error.message);
|
|
270
|
+
}
|
|
271
|
+
throw error;
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
worker.on("exit", (code: number) => {
|
|
275
|
+
const error = new Error(`Worker thread exited with code ${code}.`);
|
|
276
|
+
error.stack = undefined;
|
|
277
|
+
throw error;
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
perThreadWorkers.push(worker);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
common.logger.debug({
|
|
284
|
+
msg: "Created worker threads",
|
|
285
|
+
count: perThreadWorkers.length,
|
|
286
|
+
duration: backfillEndClock(),
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
common.metrics = new AggregateMetricsService(
|
|
290
|
+
common.metrics,
|
|
291
|
+
perThreadWorkers,
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
common.shutdown.add(() => {
|
|
295
|
+
for (const worker of perThreadWorkers) {
|
|
296
|
+
worker.postMessage({ type: "kill" });
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|