orez 0.4.4 → 0.4.6
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/dist/pg-proxy-do-backend.d.ts +5 -1
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +72 -19
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/dist/replication/change-tracker.d.ts +9 -0
- package/dist/replication/change-tracker.d.ts.map +1 -1
- package/dist/replication/change-tracker.js +15 -0
- package/dist/replication/change-tracker.js.map +1 -1
- package/dist/replication/handler.d.ts.map +1 -1
- package/dist/replication/handler.js +15 -12
- package/dist/replication/handler.js.map +1 -1
- package/dist/worker/cf-patches.d.ts.map +1 -1
- package/dist/worker/cf-patches.js +17 -0
- package/dist/worker/cf-patches.js.map +1 -1
- package/dist/zero-litestream-patch.d.ts +6 -0
- package/dist/zero-litestream-patch.d.ts.map +1 -1
- package/dist/zero-litestream-patch.js +15 -7
- package/dist/zero-litestream-patch.js.map +1 -1
- package/package.json +2 -2
|
@@ -16,6 +16,7 @@ export declare class DoBackend {
|
|
|
16
16
|
private rewriteCache;
|
|
17
17
|
private preparedStatements;
|
|
18
18
|
private portals;
|
|
19
|
+
private publicationTableInfoCache;
|
|
19
20
|
private readyPromise;
|
|
20
21
|
private inTransaction;
|
|
21
22
|
private txID;
|
|
@@ -98,6 +99,8 @@ export declare class DoBackend {
|
|
|
98
99
|
private dropTransactionSnapshots;
|
|
99
100
|
private restoreTransactionDataSnapshots;
|
|
100
101
|
private doRawBatch;
|
|
102
|
+
/** run read statements in one /batch round-trip and return per-statement results. */
|
|
103
|
+
private doBatchResults;
|
|
101
104
|
private shouldSkipStatement;
|
|
102
105
|
private executeRewrittenStatement;
|
|
103
106
|
private executeRewrittenStatements;
|
|
@@ -109,11 +112,12 @@ export declare class DoBackend {
|
|
|
109
112
|
private zeroInternalTableRefForSqliteTable;
|
|
110
113
|
private generatedIndexName;
|
|
111
114
|
private uniqueIndexName;
|
|
112
|
-
private
|
|
115
|
+
private sqliteIndexColumnsFromRows;
|
|
113
116
|
private tableIndexInfos;
|
|
114
117
|
private publicationContainsTable;
|
|
115
118
|
private publicationsForTable;
|
|
116
119
|
private publicationTableInfos;
|
|
120
|
+
private loadPublicationTableInfos;
|
|
117
121
|
private projectCatalogRow;
|
|
118
122
|
private pgTablesResult;
|
|
119
123
|
private informationSchemaColumnsResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-proxy-do-backend.d.ts","sourceRoot":"","sources":["../src/pg-proxy-do-backend.ts"],"names":[],"mappings":"AAizHA,wBAAsB,+BAA+B,CACnD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAAC,CAiCpD;AAwkCD,qBAAa,SAAS;IACpB,KAAK,UAAQ;IACb,MAAM,UAAQ;IACd,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,gBAAgB,CAAwC;IAChE,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,OAAO,CAAiC;
|
|
1
|
+
{"version":3,"file":"pg-proxy-do-backend.d.ts","sourceRoot":"","sources":["../src/pg-proxy-do-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -4558,6 +4558,13 @@ export class DoBackend {
|
|
|
4558
4558
|
rewriteCache;
|
|
4559
4559
|
preparedStatements = new Map();
|
|
4560
4560
|
portals = new Map();
|
|
4561
|
+
// catalog-query answers (pg_tables, information_schema, published-schema)
|
|
4562
|
+
// introspect every sqlite table via PRAGMAs. on a remote DO each PRAGMA is a
|
|
4563
|
+
// round-trip, and zero-cache fires several catalog queries per pg session —
|
|
4564
|
+
// uncached this serialized ~200 round-trips per query and starved /sync
|
|
4565
|
+
// connects past the client's connect budget. cache per instance, invalidated
|
|
4566
|
+
// on DDL / metadata / publication changes and on rollback.
|
|
4567
|
+
publicationTableInfoCache = null;
|
|
4561
4568
|
readyPromise = null;
|
|
4562
4569
|
// Transaction state. The Durable Object refuses raw SQL BEGIN/COMMIT/SAVEPOINT
|
|
4563
4570
|
// (Cloudflare requires ctx.storage.transaction()), so PG-style multi-call
|
|
@@ -4817,6 +4824,7 @@ export class DoBackend {
|
|
|
4817
4824
|
}
|
|
4818
4825
|
// Cached rewrites may reference metadata that the rollback just invalidated.
|
|
4819
4826
|
this.rewriteCache.clear();
|
|
4827
|
+
this.publicationTableInfoCache = null;
|
|
4820
4828
|
}
|
|
4821
4829
|
clearTransactionState() {
|
|
4822
4830
|
this.inTransaction = false;
|
|
@@ -5060,6 +5068,7 @@ export class DoBackend {
|
|
|
5060
5068
|
}
|
|
5061
5069
|
}
|
|
5062
5070
|
if (changed) {
|
|
5071
|
+
this.publicationTableInfoCache = null;
|
|
5063
5072
|
// inside an explicit tx we batch the persist to commit time. chat's
|
|
5064
5073
|
// migrations open one tx and run dozens of DDL statements; persisting
|
|
5065
5074
|
// after every one was the hot path.
|
|
@@ -5722,6 +5731,24 @@ export class DoBackend {
|
|
|
5722
5731
|
'Content-Type': 'application/json',
|
|
5723
5732
|
});
|
|
5724
5733
|
}
|
|
5734
|
+
/** run read statements in one /batch round-trip and return per-statement results. */
|
|
5735
|
+
async doBatchResults(statements) {
|
|
5736
|
+
if (statements.length === 0)
|
|
5737
|
+
return [];
|
|
5738
|
+
const resp = await this.httpClient.post(this.url('/batch'), JSON.stringify({ statements }), { 'Content-Type': 'application/json' });
|
|
5739
|
+
const parsed = JSON.parse(resp);
|
|
5740
|
+
const results = Array.isArray(parsed.results) ? parsed.results : [];
|
|
5741
|
+
return statements.map((_, index) => {
|
|
5742
|
+
const result = results[index] ?? {};
|
|
5743
|
+
const rows = (result.rows ?? []);
|
|
5744
|
+
const columns = Array.isArray(result.columns) && result.columns.length > 0
|
|
5745
|
+
? result.columns.map(String)
|
|
5746
|
+
: rows.length > 0
|
|
5747
|
+
? Object.keys(rows[0])
|
|
5748
|
+
: [];
|
|
5749
|
+
return { rows, columns, affectedRows: result.affectedRows };
|
|
5750
|
+
});
|
|
5751
|
+
}
|
|
5725
5752
|
async shouldSkipStatement(statement) {
|
|
5726
5753
|
if (statement.skipIfColumnExists &&
|
|
5727
5754
|
(await this.columnExists(statement.skipIfColumnExists.table, statement.skipIfColumnExists.column))) {
|
|
@@ -5742,6 +5769,8 @@ export class DoBackend {
|
|
|
5742
5769
|
return { rows: [], columns: [] };
|
|
5743
5770
|
if (await this.shouldSkipStatement(statement))
|
|
5744
5771
|
return { rows: [], columns: [] };
|
|
5772
|
+
if (statement.isDDL)
|
|
5773
|
+
this.publicationTableInfoCache = null;
|
|
5745
5774
|
await this.snapshotTransactionWrite(statement);
|
|
5746
5775
|
const tracking = this.trackingForStatement(statement);
|
|
5747
5776
|
const exec = await this.materializePublishedSchemaFunctions(tracking?.returningSQL ?? statement.sql, statement);
|
|
@@ -5773,6 +5802,8 @@ export class DoBackend {
|
|
|
5773
5802
|
: statement;
|
|
5774
5803
|
if (!item.sql.trim())
|
|
5775
5804
|
continue;
|
|
5805
|
+
if (item.isDDL)
|
|
5806
|
+
this.publicationTableInfoCache = null;
|
|
5776
5807
|
if (item.skipIfColumnExists || item.skipIfColumnMissing || item.skipIfTableEmpty) {
|
|
5777
5808
|
await flush();
|
|
5778
5809
|
if (item.skipIfColumnExists &&
|
|
@@ -5886,9 +5917,8 @@ export class DoBackend {
|
|
|
5886
5917
|
usedNames.add(unique);
|
|
5887
5918
|
return unique;
|
|
5888
5919
|
}
|
|
5889
|
-
|
|
5890
|
-
const
|
|
5891
|
-
const rows = result.rows
|
|
5920
|
+
sqliteIndexColumnsFromRows(xinfoRows) {
|
|
5921
|
+
const rows = xinfoRows
|
|
5892
5922
|
.map((row) => ({
|
|
5893
5923
|
seqno: Number(row.seqno ?? 0),
|
|
5894
5924
|
cid: Number(row.cid ?? -1),
|
|
@@ -5903,7 +5933,7 @@ export class DoBackend {
|
|
|
5903
5933
|
columns[row.name] = row.desc === 1 ? 'DESC' : 'ASC';
|
|
5904
5934
|
return columns;
|
|
5905
5935
|
}
|
|
5906
|
-
|
|
5936
|
+
tableIndexInfos(table, columns, primaryKey, indexListRows, indexColumnsByName) {
|
|
5907
5937
|
const usedNames = new Set();
|
|
5908
5938
|
const seenSignatures = new Set();
|
|
5909
5939
|
const indexes = [];
|
|
@@ -5938,8 +5968,7 @@ export class DoBackend {
|
|
|
5938
5968
|
continue;
|
|
5939
5969
|
addIndex(this.generatedIndexName(table, [column.name], 'key'), { [column.name]: 'ASC' }, true, false);
|
|
5940
5970
|
}
|
|
5941
|
-
const
|
|
5942
|
-
const rawIndexes = result.rows
|
|
5971
|
+
const rawIndexes = indexListRows
|
|
5943
5972
|
.map((row) => ({
|
|
5944
5973
|
seq: Number(row.seq ?? 0),
|
|
5945
5974
|
name: String(row.name ?? ''),
|
|
@@ -5952,7 +5981,7 @@ export class DoBackend {
|
|
|
5952
5981
|
for (const raw of rawIndexes) {
|
|
5953
5982
|
if (raw.partial)
|
|
5954
5983
|
continue;
|
|
5955
|
-
const indexColumns =
|
|
5984
|
+
const indexColumns = indexColumnsByName.get(raw.name) ?? {};
|
|
5956
5985
|
const names = Object.keys(indexColumns);
|
|
5957
5986
|
if (raw.origin === 'pk' && primaryKey.length > 0)
|
|
5958
5987
|
continue;
|
|
@@ -5977,15 +6006,44 @@ export class DoBackend {
|
|
|
5977
6006
|
});
|
|
5978
6007
|
}
|
|
5979
6008
|
async publicationTableInfos(publications) {
|
|
5980
|
-
|
|
6009
|
+
if (!this.publicationTableInfoCache) {
|
|
6010
|
+
this.publicationTableInfoCache = await this.loadPublicationTableInfos();
|
|
6011
|
+
}
|
|
5981
6012
|
const requested = publications?.filter((name) => this.publications.has(name)) ?? [];
|
|
6013
|
+
return this.publicationTableInfoCache.filter((info) => {
|
|
6014
|
+
if (requested.length > 0) {
|
|
6015
|
+
return requested.some((publicationName) => this.publicationContainsTable(this.publications.get(publicationName), info));
|
|
6016
|
+
}
|
|
6017
|
+
return !publications?.length;
|
|
6018
|
+
});
|
|
6019
|
+
}
|
|
6020
|
+
async loadPublicationTableInfos() {
|
|
6021
|
+
const allTables = (await this.listSqliteTables()).filter((table) => !isSystemSqliteTable(table.name));
|
|
6022
|
+
// batch table_info + index_list for every table into ONE round-trip, then
|
|
6023
|
+
// every index_xinfo into a second — per-PRAGMA round-trips to the SQL DO
|
|
6024
|
+
// made each full scan cost seconds and starve concurrent sessions.
|
|
6025
|
+
const pragmaResults = await this.doBatchResults(allTables.flatMap((table) => [
|
|
6026
|
+
`PRAGMA table_info(${quoteIdentifier(table.name)})`,
|
|
6027
|
+
`PRAGMA index_list(${quoteIdentifier(table.name)})`,
|
|
6028
|
+
]));
|
|
6029
|
+
const indexNames = [];
|
|
6030
|
+
for (let i = 0; i < allTables.length; i++) {
|
|
6031
|
+
for (const row of pragmaResults[i * 2 + 1]?.rows ?? []) {
|
|
6032
|
+
const name = String(row.name ?? '');
|
|
6033
|
+
if (name && !Number(row.partial ?? 0))
|
|
6034
|
+
indexNames.push(name);
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
const xinfoResults = await this.doBatchResults(indexNames.map((name) => `PRAGMA index_xinfo(${quoteIdentifier(name)})`));
|
|
6038
|
+
const indexColumnsByName = new Map();
|
|
6039
|
+
for (let i = 0; i < indexNames.length; i++) {
|
|
6040
|
+
indexColumnsByName.set(indexNames[i], this.sqliteIndexColumnsFromRows(xinfoResults[i]?.rows ?? []));
|
|
6041
|
+
}
|
|
5982
6042
|
const infos = [];
|
|
5983
|
-
for (
|
|
5984
|
-
|
|
5985
|
-
continue;
|
|
6043
|
+
for (let i = 0; i < allTables.length; i++) {
|
|
6044
|
+
const table = allTables[i];
|
|
5986
6045
|
const ref = this.tableRefForSqliteTable(table.name);
|
|
5987
|
-
const
|
|
5988
|
-
const columns = result.rows.map((row) => ({
|
|
6046
|
+
const columns = (pragmaResults[i * 2]?.rows ?? []).map((row) => ({
|
|
5989
6047
|
cid: Number(row.cid ?? 0),
|
|
5990
6048
|
name: String(row.name ?? ''),
|
|
5991
6049
|
type: String(row.type ?? ''),
|
|
@@ -6013,12 +6071,7 @@ export class DoBackend {
|
|
|
6013
6071
|
.map((column) => column.name),
|
|
6014
6072
|
indexes: [],
|
|
6015
6073
|
};
|
|
6016
|
-
info.indexes =
|
|
6017
|
-
if (requested.length > 0 &&
|
|
6018
|
-
!requested.some((publicationName) => this.publicationContainsTable(this.publications.get(publicationName), info)))
|
|
6019
|
-
continue;
|
|
6020
|
-
if (requested.length === 0 && publications?.length)
|
|
6021
|
-
continue;
|
|
6074
|
+
info.indexes = this.tableIndexInfos(ref, columns, info.primaryKey, pragmaResults[i * 2 + 1]?.rows ?? [], indexColumnsByName);
|
|
6022
6075
|
infos.push(info);
|
|
6023
6076
|
}
|
|
6024
6077
|
return infos;
|