orez 0.5.8 → 0.5.11

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/browser.js CHANGED
@@ -103,7 +103,7 @@ export async function startOrezBrowser(config) {
103
103
  },
104
104
  async stop() {
105
105
  await zc.stop();
106
- proxy.close();
106
+ await proxy.close();
107
107
  resetReplicationState();
108
108
  await Promise.all([pgPostgres.close(), pgCvr.close(), pgCdb.close()]);
109
109
  },
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ import type { PGlite } from '@electric-sql/pglite';
20
20
  export type BrowserProxyDbName = 'postgres' | 'zero_cvr' | 'zero_cdb';
21
21
  export interface BrowserProxy {
22
22
  handleConnection(port: MessagePort): void;
23
- close(): void;
23
+ close(): Promise<void>;
24
24
  createExternalSession(dbName?: BrowserProxyDbName): BrowserProxyExternalSession;
25
25
  /**
26
26
  * mutex-coordinated query for out-of-band JSON callers (e.g. soot's
@@ -1 +1 @@
1
- {"version":3,"file":"pg-proxy-browser.d.ts","sourceRoot":"","sources":["../src/pg-proxy-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AA+sBlD;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAErE,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACzC,KAAK,IAAI,IAAI,CAAA;IACb,qBAAqB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,2BAA2B,CAAA;IAC/E;;;;;;;;OAQG;IACH,KAAK,CACH,MAAM,EAAE,kBAAkB,EAC1B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtD,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CACxF;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CACH,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AA4CD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,GAAG,eAAe,EACjC,MAAM,EAAE;IACN,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GACA,OAAO,CAAC,YAAY,CAAC,CA2uCvB"}
1
+ {"version":3,"file":"pg-proxy-browser.d.ts","sourceRoot":"","sources":["../src/pg-proxy-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AA+sBlD;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAErE,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,qBAAqB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,2BAA2B,CAAA;IAC/E;;;;;;;;OAQG;IACH,KAAK,CACH,MAAM,EAAE,kBAAkB,EAC1B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtD,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CACxF;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CACH,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AA4CD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,GAAG,eAAe,EACjC,MAAM,EAAE;IACN,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GACA,OAAO,CAAC,YAAY,CAAC,CA20CvB"}
@@ -771,12 +771,18 @@ export async function createBrowserProxy(dbInput, config) {
771
771
  });
772
772
  }
773
773
  let closed = false;
774
+ let closePromise = null;
774
775
  const activeConnectionClosers = new Set();
776
+ const unreportedConnectionCleanupErrors = new Set();
775
777
  function handleConnection(port) {
776
778
  if (closed) {
777
779
  port.close();
778
780
  return;
779
781
  }
782
+ const closePendingConnection = async () => {
783
+ port.close();
784
+ };
785
+ activeConnectionClosers.add(closePendingConnection);
780
786
  port.start();
781
787
  // peek at the first message to detect replication connections.
782
788
  // replication connections bypass pg-gateway entirely and are handled
@@ -786,6 +792,10 @@ export async function createBrowserProxy(dbInput, config) {
786
792
  const buffered = [];
787
793
  let handlerInstalled = false;
788
794
  port.onmessage = (ev) => {
795
+ if (closed) {
796
+ port.close();
797
+ return;
798
+ }
789
799
  if (handlerInstalled)
790
800
  return; // shouldn't happen — handler replaced port.onmessage
791
801
  buffered.push(ev);
@@ -795,6 +805,7 @@ export async function createBrowserProxy(dbInput, config) {
795
805
  if (!(data instanceof Uint8Array) || data.length < 8) {
796
806
  handlerInstalled = true;
797
807
  handleRegularConnection(port, ev);
808
+ activeConnectionClosers.delete(closePendingConnection);
798
809
  // flush buffered messages to the new handler
799
810
  for (let i = 1; i < buffered.length; i++) {
800
811
  port.onmessage?.(buffered[i]);
@@ -813,6 +824,7 @@ export async function createBrowserProxy(dbInput, config) {
813
824
  // in browser Web Workers (same root cause as patches #9, #18, #20).
814
825
  handleRawConnection(port, data, params, getDbContext(dbName), isRepl);
815
826
  handlerInstalled = true;
827
+ activeConnectionClosers.delete(closePendingConnection);
816
828
  // flush any messages that arrived while we were processing the startup
817
829
  for (let i = 1; i < buffered.length; i++) {
818
830
  if (port.onmessage) {
@@ -855,43 +867,53 @@ export async function createBrowserProxy(dbInput, config) {
855
867
  const connId = {};
856
868
  const dbName = params.database || 'postgres';
857
869
  let connClosed = false;
858
- let sessionClosed = false;
859
- const closeSession = async () => {
860
- if (sessionClosed)
861
- return;
862
- sessionClosed = true;
863
- activeConnectionClosers.delete(closeSession);
864
- // a connection torn down mid-pipeline still OWNS the db mutex. a dead
865
- // pipeline can never send its Sync, so without this release the mutex
866
- // is leaked forever and every later connection on this db (including
867
- // the next embed generation after an idle-hibernation teardown) blocks
868
- // in mutex.acquire() before its first statement. when a statement is
869
- // still executing, the pipeline continuation performs this cleanup
870
- // after it settles instead (pipelineExecInFlight).
871
- if (pipelineMutexHeld && !pipelineExecInFlight) {
872
- pipelineMutexHeld = false;
873
- try {
874
- await rollbackOwnTransaction();
870
+ let closeSessionPromise = null;
871
+ const closeSession = () => {
872
+ if (closeSessionPromise)
873
+ return closeSessionPromise;
874
+ connClosed = true;
875
+ closeSessionPromise = (async () => {
876
+ port.close();
877
+ // a connection torn down mid-pipeline still OWNS the db mutex. a dead
878
+ // pipeline can never send its Sync, so without this release the mutex
879
+ // is leaked forever and every later connection on this db (including
880
+ // the next embed generation after an idle-hibernation teardown) blocks
881
+ // in mutex.acquire() before its first statement. when a statement is
882
+ // still executing, the pipeline continuation performs this cleanup
883
+ // after it settles instead (pipelineExecInFlight).
884
+ if (pipelineExecInFlight)
885
+ await pipelineIdlePromise;
886
+ if (pipelineMutexHeld) {
887
+ pipelineMutexHeld = false;
888
+ try {
889
+ await rollbackOwnTransaction();
890
+ }
891
+ finally {
892
+ mutex.release();
893
+ }
875
894
  }
876
- finally {
877
- mutex.release();
895
+ else {
896
+ await mutex.acquire();
897
+ try {
898
+ await rollbackOwnTransaction();
899
+ }
900
+ finally {
901
+ mutex.release();
902
+ }
878
903
  }
879
- }
880
- try {
881
904
  await scopedContext.close();
882
- }
883
- catch { }
905
+ })();
906
+ void closeSessionPromise.then(() => activeConnectionClosers.delete(closeSession), (error) => {
907
+ activeConnectionClosers.delete(closeSession);
908
+ unreportedConnectionCleanupErrors.add(error);
909
+ });
910
+ return closeSessionPromise;
884
911
  };
885
912
  activeConnectionClosers.add(closeSession);
886
913
  // roll back this connection's open transaction. caller must hold the mutex.
887
914
  const rollbackOwnTransaction = async () => {
888
915
  if (txState.owner === connId && txState.status !== 0x49) {
889
- try {
890
- await db.exec('ROLLBACK');
891
- }
892
- catch {
893
- // db is closed or rollback failed — ignore
894
- }
916
+ await db.exec('ROLLBACK');
895
917
  txState.status = 0x49;
896
918
  txState.owner = null;
897
919
  }
@@ -959,6 +981,18 @@ export async function createBrowserProxy(dbInput, config) {
959
981
  // statement currently executing inside the held pipeline — closeSession
960
982
  // must not release the mutex under it (see closeSession above)
961
983
  let pipelineExecInFlight = false;
984
+ let resolvePipelineIdle = () => { };
985
+ let pipelineIdlePromise = Promise.resolve();
986
+ const beginPipelineExec = () => {
987
+ pipelineExecInFlight = true;
988
+ pipelineIdlePromise = new Promise((resolve) => {
989
+ resolvePipelineIdle = resolve;
990
+ });
991
+ };
992
+ const endPipelineExec = () => {
993
+ pipelineExecInFlight = false;
994
+ resolvePipelineIdle();
995
+ };
962
996
  let extWritePending = false;
963
997
  let pipelineBuffer = [];
964
998
  // remember the most recent Parse / SimpleQuery for diagnostic logging when
@@ -1163,7 +1197,7 @@ export async function createBrowserProxy(dbInput, config) {
1163
1197
  const combined = concatUint8Arrays(pipelineBuffer);
1164
1198
  pipelineBuffer = [];
1165
1199
  let flushResult;
1166
- pipelineExecInFlight = true;
1200
+ beginPipelineExec();
1167
1201
  try {
1168
1202
  flushResult = await db.execProtocolRaw(combined, { syncToFs: false });
1169
1203
  }
@@ -1174,19 +1208,7 @@ export async function createBrowserProxy(dbInput, config) {
1174
1208
  return;
1175
1209
  }
1176
1210
  finally {
1177
- pipelineExecInFlight = false;
1178
- }
1179
- if (sessionClosed && pipelineMutexHeld) {
1180
- // session torn down while this statement was executing —
1181
- // closeSession skipped its cleanup, finish it here
1182
- pipelineMutexHeld = false;
1183
- try {
1184
- await rollbackOwnTransaction();
1185
- }
1186
- finally {
1187
- mutex.release();
1188
- }
1189
- return;
1211
+ endPipelineExec();
1190
1212
  }
1191
1213
  flushResult = stripResponseMessages(flushResult, true);
1192
1214
  write(flushResult);
@@ -1199,7 +1221,7 @@ export async function createBrowserProxy(dbInput, config) {
1199
1221
  pipelineBuffer = [];
1200
1222
  let result;
1201
1223
  const t0 = performance.now();
1202
- pipelineExecInFlight = true;
1224
+ beginPipelineExec();
1203
1225
  try {
1204
1226
  result = await db.execProtocolRaw(combined, { syncToFs: false });
1205
1227
  }
@@ -1210,7 +1232,7 @@ export async function createBrowserProxy(dbInput, config) {
1210
1232
  return;
1211
1233
  }
1212
1234
  finally {
1213
- pipelineExecInFlight = false;
1235
+ endPipelineExec();
1214
1236
  }
1215
1237
  const dt = performance.now() - t0;
1216
1238
  if (isDebugWire() && dt > 100)
@@ -1327,17 +1349,25 @@ export async function createBrowserProxy(dbInput, config) {
1327
1349
  // not release the mutex under it; the pipeline continuation finishes the
1328
1350
  // cleanup after the statement settles.
1329
1351
  let pipelineExecInFlight = false;
1352
+ let resolvePipelineIdle = () => { };
1353
+ let pipelineIdlePromise = Promise.resolve();
1354
+ const beginPipelineExec = () => {
1355
+ pipelineExecInFlight = true;
1356
+ pipelineIdlePromise = new Promise((resolve) => {
1357
+ resolvePipelineIdle = resolve;
1358
+ });
1359
+ };
1360
+ const endPipelineExec = () => {
1361
+ pipelineExecInFlight = false;
1362
+ resolvePipelineIdle();
1363
+ };
1330
1364
  // connection closed flag
1331
1365
  let connClosed = false;
1366
+ let cleanupPromise = null;
1332
1367
  // roll back this connection's open transaction. caller must hold the mutex.
1333
1368
  const rollbackOwnTransaction = async (db, txState) => {
1334
1369
  if (txState.owner === connId && txState.status !== 0x49) {
1335
- try {
1336
- await db.exec('ROLLBACK');
1337
- }
1338
- catch {
1339
- // db is closed or rollback failed — ignore
1340
- }
1370
+ await db.exec('ROLLBACK');
1341
1371
  txState.status = 0x49;
1342
1372
  txState.owner = null;
1343
1373
  }
@@ -1350,32 +1380,30 @@ export async function createBrowserProxy(dbInput, config) {
1350
1380
  // pollution that 2eb1873 fixed on the node side. browser cleanup was
1351
1381
  // missed and showed up as "current transaction is aborted, commands
1352
1382
  // ignored" when a foreign connection closed mid-someone-else's-txn.
1353
- const cleanup = async () => {
1354
- if (connClosed)
1355
- return;
1383
+ const cleanup = () => {
1384
+ if (cleanupPromise)
1385
+ return cleanupPromise;
1356
1386
  connClosed = true;
1357
- activeConnectionClosers.delete(cleanup);
1358
- // replication connections don't own a transaction — skip ROLLBACK
1359
- if (isReplicationConnection)
1360
- return;
1361
- try {
1387
+ cleanupPromise = (async () => {
1388
+ port.close();
1389
+ // replication connections don't own a transaction — skip ROLLBACK
1390
+ if (isReplicationConnection)
1391
+ return;
1362
1392
  const { db, mutex, txState } = getDbContext(dbName);
1393
+ if (pipelineExecInFlight)
1394
+ await pipelineIdlePromise;
1363
1395
  if (pipelineMutexHeld) {
1364
1396
  // this connection died mid-pipeline and still OWNS the mutex. a
1365
1397
  // dead pipeline can never send its Sync, so without this release
1366
1398
  // the mutex is leaked forever and every later connection on this
1367
1399
  // db (including the next embed generation after idle-hibernation
1368
1400
  // teardown) blocks in mutex.acquire() before its first statement.
1369
- // when a statement is in flight, the pipeline continuation does
1370
- // this exact cleanup after it settles.
1371
- if (!pipelineExecInFlight) {
1372
- pipelineMutexHeld = false;
1373
- try {
1374
- await rollbackOwnTransaction(db, txState);
1375
- }
1376
- finally {
1377
- mutex.release();
1378
- }
1401
+ pipelineMutexHeld = false;
1402
+ try {
1403
+ await rollbackOwnTransaction(db, txState);
1404
+ }
1405
+ finally {
1406
+ mutex.release();
1379
1407
  }
1380
1408
  return;
1381
1409
  }
@@ -1386,10 +1414,12 @@ export async function createBrowserProxy(dbInput, config) {
1386
1414
  finally {
1387
1415
  mutex.release();
1388
1416
  }
1389
- }
1390
- catch {
1391
- // instance may have been replaced during reset, ignore
1392
- }
1417
+ })();
1418
+ void cleanupPromise.then(() => activeConnectionClosers.delete(cleanup), (error) => {
1419
+ activeConnectionClosers.delete(cleanup);
1420
+ unreportedConnectionCleanupErrors.add(error);
1421
+ });
1422
+ return cleanupPromise;
1393
1423
  };
1394
1424
  activeConnectionClosers.add(cleanup);
1395
1425
  try {
@@ -1486,7 +1516,7 @@ export async function createBrowserProxy(dbInput, config) {
1486
1516
  data = interceptQuery(data);
1487
1517
  const t1 = performance.now();
1488
1518
  let result;
1489
- pipelineExecInFlight = true;
1519
+ beginPipelineExec();
1490
1520
  try {
1491
1521
  result = await db.execProtocolRaw(data, { syncToFs: false });
1492
1522
  }
@@ -1496,7 +1526,7 @@ export async function createBrowserProxy(dbInput, config) {
1496
1526
  throw err;
1497
1527
  }
1498
1528
  finally {
1499
- pipelineExecInFlight = false;
1529
+ endPipelineExec();
1500
1530
  }
1501
1531
  const t2 = performance.now();
1502
1532
  proxyStats.totalExecMs += t2 - t1;
@@ -1518,18 +1548,6 @@ export async function createBrowserProxy(dbInput, config) {
1518
1548
  signalWrite();
1519
1549
  }
1520
1550
  }
1521
- else if (connClosed) {
1522
- // the connection died while this statement was executing, so
1523
- // cleanup skipped its release (pipelineExecInFlight). no Sync
1524
- // can ever arrive — roll back and release here instead.
1525
- pipelineMutexHeld = false;
1526
- try {
1527
- await rollbackOwnTransaction(db, txState);
1528
- }
1529
- finally {
1530
- mutex.release();
1531
- }
1532
- }
1533
1551
  else {
1534
1552
  // strip ReadyForQuery from non-Sync pipeline messages
1535
1553
  // result = stripResponseMessages(result, true) // disabled for debugging
@@ -1707,11 +1725,59 @@ export async function createBrowserProxy(dbInput, config) {
1707
1725
  txState.owner = owner;
1708
1726
  }
1709
1727
  const defaultExternalOwner = {};
1728
+ const closedExternalOwners = new WeakSet();
1729
+ function createExternalOwnerCloser(owner, dbNames) {
1730
+ let closing = null;
1731
+ const closeOwner = () => {
1732
+ if (closing)
1733
+ return closing;
1734
+ closedExternalOwners.add(owner);
1735
+ closing = (async () => {
1736
+ const contexts = new Map();
1737
+ for (const dbName of dbNames) {
1738
+ const context = getDbContext(dbName);
1739
+ contexts.set(context.txState, context);
1740
+ }
1741
+ const results = await Promise.allSettled([...contexts.values()].map(async ({ db, mutex, txState }) => {
1742
+ await mutex.acquire();
1743
+ try {
1744
+ if (txState.owner === owner && txState.status !== 0x49) {
1745
+ await db.exec('ROLLBACK');
1746
+ txState.status = 0x49;
1747
+ txState.owner = null;
1748
+ }
1749
+ }
1750
+ finally {
1751
+ mutex.release();
1752
+ }
1753
+ }));
1754
+ const errors = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
1755
+ if (errors.length === 1)
1756
+ throw errors[0];
1757
+ if (errors.length > 1) {
1758
+ throw new AggregateError(errors, 'browser proxy external cleanup failed');
1759
+ }
1760
+ })();
1761
+ void closing.then(() => activeConnectionClosers.delete(closeOwner), (error) => {
1762
+ activeConnectionClosers.delete(closeOwner);
1763
+ unreportedConnectionCleanupErrors.add(error);
1764
+ });
1765
+ return closing;
1766
+ };
1767
+ activeConnectionClosers.add(closeOwner);
1768
+ return closeOwner;
1769
+ }
1770
+ createExternalOwnerCloser(defaultExternalOwner, ['postgres', 'zero_cvr', 'zero_cdb']);
1710
1771
  async function externalQuery(dbName, sql, params, owner = defaultExternalOwner) {
1711
- if (closed)
1772
+ if (closed || closedExternalOwners.has(owner)) {
1712
1773
  throw new Error('pg-proxy is closed');
1774
+ }
1713
1775
  const { db, mutex, txState } = getDbContext(dbName);
1714
1776
  await acquireForOwner(db, mutex, txState, owner);
1777
+ if (closed || closedExternalOwners.has(owner)) {
1778
+ mutex.release();
1779
+ throw new Error('pg-proxy is closed');
1780
+ }
1715
1781
  try {
1716
1782
  const result = await db.query(sql, params);
1717
1783
  updateExternalTxStateAfterSuccess(txState, owner, sql);
@@ -1730,10 +1796,15 @@ export async function createBrowserProxy(dbInput, config) {
1730
1796
  }
1731
1797
  }
1732
1798
  async function externalExec(dbName, sql, owner = defaultExternalOwner) {
1733
- if (closed)
1799
+ if (closed || closedExternalOwners.has(owner)) {
1734
1800
  throw new Error('pg-proxy is closed');
1801
+ }
1735
1802
  const { db, mutex, txState } = getDbContext(dbName);
1736
1803
  await acquireForOwner(db, mutex, txState, owner);
1804
+ if (closed || closedExternalOwners.has(owner)) {
1805
+ mutex.release();
1806
+ throw new Error('pg-proxy is closed');
1807
+ }
1737
1808
  try {
1738
1809
  const result = await db.exec(sql);
1739
1810
  updateExternalTxStateAfterSuccess(txState, owner, sql);
@@ -1752,40 +1823,45 @@ export async function createBrowserProxy(dbInput, config) {
1752
1823
  }
1753
1824
  function createExternalSession(dbName = 'postgres') {
1754
1825
  const owner = {};
1826
+ let sessionClosed = false;
1827
+ const closeOwner = createExternalOwnerCloser(owner, [dbName]);
1755
1828
  return {
1756
1829
  query(sql, params) {
1830
+ if (sessionClosed)
1831
+ return Promise.reject(new Error('pg-proxy session is closed'));
1757
1832
  return externalQuery(dbName, sql, params, owner);
1758
1833
  },
1759
1834
  exec(sql) {
1835
+ if (sessionClosed)
1836
+ return Promise.reject(new Error('pg-proxy session is closed'));
1760
1837
  return externalExec(dbName, sql, owner);
1761
1838
  },
1762
- async close() {
1763
- const { db, mutex, txState } = getDbContext(dbName);
1764
- await mutex.acquire();
1765
- try {
1766
- if (txState.owner === owner && txState.status !== 0x49) {
1767
- try {
1768
- await db.exec('ROLLBACK');
1769
- }
1770
- catch { }
1771
- txState.status = 0x49;
1772
- txState.owner = null;
1773
- }
1774
- }
1775
- finally {
1776
- mutex.release();
1777
- }
1839
+ close() {
1840
+ sessionClosed = true;
1841
+ return closeOwner();
1778
1842
  },
1779
1843
  };
1780
1844
  }
1781
1845
  return {
1782
1846
  handleConnection,
1783
1847
  close() {
1848
+ if (closePromise)
1849
+ return closePromise;
1784
1850
  closed = true;
1785
1851
  signalPending = false;
1786
- for (const closeConnection of activeConnectionClosers) {
1787
- void closeConnection();
1788
- }
1852
+ closePromise = (async () => {
1853
+ const results = await Promise.allSettled([...activeConnectionClosers].map((closeConnection) => Promise.resolve().then(() => closeConnection())));
1854
+ const errors = new Set(unreportedConnectionCleanupErrors);
1855
+ for (const result of results) {
1856
+ if (result.status === 'rejected')
1857
+ errors.add(result.reason);
1858
+ }
1859
+ unreportedConnectionCleanupErrors.clear();
1860
+ if (errors.size > 0) {
1861
+ throw new AggregateError([...errors], 'browser proxy connection cleanup failed');
1862
+ }
1863
+ })();
1864
+ return closePromise;
1789
1865
  },
1790
1866
  createExternalSession,
1791
1867
  query: externalQuery,