@delali/sirannon-db 0.3.5-next.69 → 0.3.5-next.72

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.
Files changed (91) hide show
  1. package/README.md +2 -0
  2. package/dist/backup/index.d.ts +5 -5
  3. package/dist/backup/index.mjs +4 -3
  4. package/dist/backup-scheduler/index.d.ts +2 -2
  5. package/dist/backup-scheduler/index.mjs +5 -4
  6. package/dist/{change-tracker-DqCdeEyx.d.ts → change-tracker-Dpo99EI-.d.ts} +24 -7
  7. package/dist/{chunk-ADNWEHGZ.mjs → chunk-3VTT3VU6.mjs} +15 -7
  8. package/dist/chunk-75IBRE73.mjs +55 -0
  9. package/dist/{chunk-KJLNYOOL.mjs → chunk-AHCMO4YL.mjs} +19 -10
  10. package/dist/chunk-AP4367HK.mjs +1080 -0
  11. package/dist/chunk-BGJ5JVYL.mjs +62 -0
  12. package/dist/{chunk-NVSQ2T5Q.mjs → chunk-BTUD6XQO.mjs} +16 -5
  13. package/dist/{chunk-R7GBXNTO.mjs → chunk-BUWJH3D3.mjs} +2 -55
  14. package/dist/chunk-D3YF2G7X.mjs +147 -0
  15. package/dist/chunk-DBN57KVR.mjs +171 -0
  16. package/dist/chunk-DDIHBUEN.mjs +240 -0
  17. package/dist/{chunk-FJPR2CJX.mjs → chunk-DKML5425.mjs} +2 -2
  18. package/dist/chunk-E2GRX4ZD.mjs +30 -0
  19. package/dist/{chunk-NZGSDALX.mjs → chunk-G4AG3ESO.mjs} +217 -76
  20. package/dist/{chunk-QBBLSQHQ.mjs → chunk-HO2XTXVX.mjs} +1 -8
  21. package/dist/chunk-ISDT4RBD.mjs +149 -0
  22. package/dist/{chunk-IEKIYO4V.mjs → chunk-JAQ2I4OT.mjs} +5 -5
  23. package/dist/{chunk-2O3PP4CF.mjs → chunk-JFVEGN7J.mjs} +44 -18
  24. package/dist/{chunk-2ES3DT4A.mjs → chunk-JZL64CZZ.mjs} +66 -6
  25. package/dist/chunk-K43WJORM.mjs +23 -0
  26. package/dist/{chunk-55YRLSM2.mjs → chunk-KOTBP4AW.mjs} +27 -4
  27. package/dist/{chunk-3BZLZ47R.mjs → chunk-L6EX6K27.mjs} +2 -2
  28. package/dist/chunk-PJRCMG7L.mjs +232 -0
  29. package/dist/{chunk-HR7K3GZW.mjs → chunk-RLBKZZ24.mjs} +5 -1
  30. package/dist/{chunk-ESTZZPT5.mjs → chunk-RPWBYASV.mjs} +391 -33
  31. package/dist/chunk-SB3MIFLG.mjs +1374 -0
  32. package/dist/chunk-SEL4A4WT.mjs +156 -0
  33. package/dist/{chunk-6AOJCNRU.mjs → chunk-UHUDPQFI.mjs} +3 -3
  34. package/dist/{chunk-4KASJKKK.mjs → chunk-UIDQGPJY.mjs} +147 -6
  35. package/dist/{chunk-VO3ZWA2G.mjs → chunk-WXPAWGTE.mjs} +255 -46
  36. package/dist/chunk-ZFFUVYYE.mjs +439 -0
  37. package/dist/client/index.d.ts +26 -18
  38. package/dist/client/index.mjs +105 -17
  39. package/dist/client/topology.d.ts +12 -10
  40. package/dist/client/topology.mjs +17 -7
  41. package/dist/{client-base-BxTocU1x.d.ts → client-base-Doaqwrx3.d.ts} +36 -9
  42. package/dist/{client-streams-YKANXMWO.mjs → client-streams-MKPE4MXW.mjs} +6 -6
  43. package/dist/codegen/cli.mjs +3 -2
  44. package/dist/codegen/index.mjs +3 -2
  45. package/dist/core/index.d.ts +59 -16
  46. package/dist/core/index.mjs +1169 -438
  47. package/dist/core/writer-worker.mjs +57 -9
  48. package/dist/{database-backup-DcLhxoa1.d.ts → database-backup-BwTNiBm2.d.ts} +1 -1
  49. package/dist/{database-CGDsXW1K.d.ts → database-fz-8CJBP.d.ts} +365 -90
  50. package/dist/driver/better-sqlite3.d.ts +20 -2
  51. package/dist/driver/better-sqlite3.mjs +212 -36
  52. package/dist/driver/bun.d.ts +1 -1
  53. package/dist/driver/bun.mjs +21 -33
  54. package/dist/driver/expo.d.ts +1 -1
  55. package/dist/driver/expo.mjs +35 -5
  56. package/dist/driver/node.d.ts +1 -1
  57. package/dist/driver/node.mjs +90 -23
  58. package/dist/driver/wa-sqlite.d.ts +1 -1
  59. package/dist/driver/wa-sqlite.mjs +215 -13
  60. package/dist/file-migrations/index.d.ts +1 -1
  61. package/dist/file-migrations/index.mjs +13 -8
  62. package/dist/{forward-rpc-VRWFZXHN.mjs → forward-rpc-S7NMLBX7.mjs} +1 -1
  63. package/dist/{primary-wins-CHNOYuN7.d.ts → primary-wins-BnNAEjwB.d.ts} +7 -6
  64. package/dist/{protocol-DFpNNsIT.d.ts → protocol-DZSYSv0S.d.ts} +1 -1
  65. package/dist/replication/coordinator/etcd.d.ts +22 -5
  66. package/dist/replication/coordinator/etcd.mjs +349 -271
  67. package/dist/replication/index.d.ts +269 -41
  68. package/dist/replication/index.mjs +2197 -1155
  69. package/dist/{restore-options-CH8mE-Tb.d.ts → restore-options-CcMukOLO.d.ts} +1 -1
  70. package/dist/server/index.d.ts +55 -19
  71. package/dist/server/index.mjs +869 -310
  72. package/dist/{server-options-aYtCkefX.d.ts → server-options-B9CsAZp5.d.ts} +9 -7
  73. package/dist/{server-streams-24XL4T43.mjs → server-streams-SBYCHWWM.mjs} +36 -59
  74. package/dist/{sirannon-J3EgPVD7.d.ts → sirannon-D0CjDULa.d.ts} +2 -2
  75. package/dist/transport/grpc.d.ts +26 -7
  76. package/dist/transport/grpc.mjs +45 -23
  77. package/dist/transport/memory.d.ts +5 -5
  78. package/dist/transport/memory.mjs +9 -3
  79. package/dist/{types-DqODKeOq.d.ts → types-BG31TtrQ.d.ts} +17 -0
  80. package/dist/{types-BrAiDGOb.d.ts → types-BlZ9GG1a.d.ts} +33 -8
  81. package/dist/{types-Dc8oWlxj.d.ts → types-DTmi7pXp.d.ts} +198 -15
  82. package/dist/{types-guEKSzMr.d.ts → types-MczwKtul.d.ts} +214 -135
  83. package/package.json +18 -7
  84. package/dist/chunk-52XW3Z76.mjs +0 -256
  85. package/dist/chunk-A3PHCO6W.mjs +0 -645
  86. package/dist/chunk-ER7ODTDA.mjs +0 -23
  87. package/dist/chunk-GVYLZVUZ.mjs +0 -58
  88. package/dist/chunk-MVSES6MS.mjs +0 -22
  89. package/dist/chunk-ZN4HI5FK.mjs +0 -907
  90. package/dist/chunk-ZYWI45EN.mjs +0 -299
  91. package/dist/errors-CJUkQ-KL.d.ts +0 -199
package/README.md CHANGED
@@ -131,6 +131,8 @@ const subscription = db
131
131
 
132
132
  With a filter, you receive each change in a row's membership of the set that the filter matches. When an order's `status` changes from `pending` to `shipped`, the handler receives an insert, because the row joins the set. When an order's `status` changes away from `shipped`, the handler receives a delete with the previous row in `oldRow`. Read `event.type` as the row joining or leaving the set, because the handler receives the same event for a real insert and for a row that joins the set.
133
133
 
134
+ When a `REPLACE` deletes a stored row because the new row has the same primary key or the same value in a unique column, Sirannon calls the handler with a delete for that row before it calls the handler with the write. If your own `BEFORE` trigger on the table inserts or updates a row in the same statement and the `REPLACE` then deletes that row, Sirannon may report no delete for it.
135
+
134
136
  A live query holds the current result of a query and updates its rows from those same events:
135
137
 
136
138
  ```ts
@@ -1,8 +1,8 @@
1
- import { B as BackupDestination, f as BackupRunReport } from '../types-Dc8oWlxj.js';
2
- export { g as BackupChain, h as BackupChainBase, i as BackupChainChange, j as BackupChainPosition, k as BackupChainRecord, l as BackupCycle, m as BackupCycleError, n as BackupCycleOptions, o as BackupCycleStatus, p as BackupFileReport, q as BackupGroupMembership, r as BackupGroupSource, s as BackupLogPosition, t as BackupNodePreference, u as BackupPiece, v as BackupProgress, w as BackupSkip, x as BackupSkipReason, y as BackupToDestinationOptions, z as BackupVerifyResult, C as DEFAULT_CHAIN_NAME, E as chainLogName, F as readBackupChains, G as verifyBackupRecord } from '../types-Dc8oWlxj.js';
3
- export { B as BackupCapabilities, a as BackupChainLocation, b as BackupRestorePlan, c as BackupSafeToDeleteOptions, d as backupPiecesSafeToDelete, p as planBackupRestore } from '../database-backup-DcLhxoa1.js';
4
- import { B as BackupRestoreOptions, a as BackupRestoreReport } from '../restore-options-CH8mE-Tb.js';
5
- export { b as BackupRestoreProgress } from '../restore-options-CH8mE-Tb.js';
1
+ import { B as BackupDestination, g as BackupRunReport } from '../types-DTmi7pXp.js';
2
+ export { h as BackupChain, i as BackupChainBase, j as BackupChainChange, k as BackupChainPosition, l as BackupChainRecord, m as BackupCycle, n as BackupCycleError, o as BackupCycleOptions, p as BackupCycleStatus, q as BackupFileReport, r as BackupGroupMembership, s as BackupGroupSource, t as BackupLogPosition, u as BackupNodePreference, v as BackupPiece, w as BackupProgress, x as BackupSkip, y as BackupSkipReason, z as BackupToDestinationOptions, C as BackupVerifyResult, E as DEFAULT_CHAIN_NAME, F as chainLogName, G as readBackupChains, H as verifyBackupRecord } from '../types-DTmi7pXp.js';
3
+ export { B as BackupCapabilities, a as BackupChainLocation, b as BackupRestorePlan, c as BackupSafeToDeleteOptions, d as backupPiecesSafeToDelete, p as planBackupRestore } from '../database-backup-BwTNiBm2.js';
4
+ import { B as BackupRestoreOptions, a as BackupRestoreReport } from '../restore-options-CcMukOLO.js';
5
+ export { b as BackupRestoreProgress } from '../restore-options-CcMukOLO.js';
6
6
  import '../query-types-5B02ixH0.js';
7
7
 
8
8
  /** The byte and piece counts for one file that Sirannon assembles from a destination.
@@ -1,8 +1,9 @@
1
- export { assembleFromDestination, restoreBackup } from '../chunk-3BZLZ47R.mjs';
1
+ export { assembleFromDestination, restoreBackup } from '../chunk-L6EX6K27.mjs';
2
2
  export { backupPiecesSafeToDelete, planBackupRestore } from '../chunk-YW7IKQ7T.mjs';
3
3
  export { verifyBackupRecord } from '../chunk-DX4WGJL7.mjs';
4
4
  import '../chunk-QGVRRKB2.mjs';
5
- import '../chunk-R7GBXNTO.mjs';
5
+ import '../chunk-BUWJH3D3.mjs';
6
6
  export { DEFAULT_CHAIN_NAME, chainLogName, readBackupChains } from '../chunk-CZL4D3BM.mjs';
7
- import '../chunk-QBBLSQHQ.mjs';
7
+ import '../chunk-BGJ5JVYL.mjs';
8
+ import '../chunk-HO2XTXVX.mjs';
8
9
  import '../chunk-KINDFBQP.mjs';
@@ -1,5 +1,5 @@
1
- import { I as SQLiteConnection, J as BackupFileCopy, K as BackupRunRequest, f as BackupRunReport, L as BackupScheduleRequest } from '../types-Dc8oWlxj.js';
2
- export { p as BackupFileReport, O as BackupScheduleOptions, R as RunExclusive } from '../types-Dc8oWlxj.js';
1
+ import { J as SQLiteConnection, K as BackupFileCopy, L as BackupRunRequest, g as BackupRunReport, O as BackupScheduleRequest } from '../types-DTmi7pXp.js';
2
+ export { q as BackupFileReport, P as BackupScheduleOptions, R as RunExclusive } from '../types-DTmi7pXp.js';
3
3
  import '../query-types-5B02ixH0.js';
4
4
 
5
5
  /** What a runtime supplies so that Sirannon can send a copy to a destination without writing a local file.
@@ -1,6 +1,7 @@
1
- export { BackupScheduler } from '../chunk-NVSQ2T5Q.mjs';
1
+ export { BackupScheduler } from '../chunk-BTUD6XQO.mjs';
2
2
  import '../chunk-W67A4H2E.mjs';
3
- import '../chunk-KJLNYOOL.mjs';
4
- import '../chunk-R7GBXNTO.mjs';
5
- import '../chunk-QBBLSQHQ.mjs';
3
+ import '../chunk-AHCMO4YL.mjs';
4
+ import '../chunk-BUWJH3D3.mjs';
5
+ import '../chunk-BGJ5JVYL.mjs';
6
+ import '../chunk-HO2XTXVX.mjs';
6
7
  import '../chunk-KINDFBQP.mjs';
@@ -1,7 +1,7 @@
1
- import { I as SQLiteConnection } from './types-Dc8oWlxj.js';
1
+ import { J as SQLiteConnection } from './types-DTmi7pXp.js';
2
2
  import { C as ChangeEvent } from './query-types-5B02ixH0.js';
3
3
 
4
- type PruneBoundarySource = 'device-sync' | 'replication' | 'device-cursors';
4
+ type PruneBoundarySource = 'device-sync' | 'device-push-cursor' | 'replication' | 'device-cursors';
5
5
 
6
6
  /**
7
7
  * Configures a change tracker's retention period, change log table, and poll size.
@@ -32,6 +32,7 @@ interface ChangeTrackerOptions {
32
32
  */
33
33
  declare class ChangeTracker {
34
34
  private readonly watched;
35
+ private readonly watchedByFoldedName;
35
36
  private lastSeq;
36
37
  private readonly retentionMs;
37
38
  private readonly changesTable;
@@ -42,24 +43,36 @@ declare class ChangeTracker {
42
43
  private readonly stmtCache;
43
44
  private readonly pruneBoundaries;
44
45
  private lastPollAtTxBoundary;
46
+ private watchQueue;
45
47
  constructor(options?: ChangeTrackerOptions);
46
48
  /**
47
49
  * Installs change-capture triggers on a table, so that every later write to it adds a row to the change log.
48
50
  *
51
+ * The tracker matches the name to an ordinary table as SQLite does, ignoring the case of ASCII letters, and records every change under the name that the schema stores. A name that matches no ordinary table, such as the name of a view or a virtual table, fails with `CDC_ERROR`. The tracker queues each call behind the one before it, so concurrent calls on one connection never open overlapping transactions.
52
+ *
49
53
  * @param conn - The writer connection on which the tracker creates the triggers.
50
54
  * @param table - The name of the table to watch.
51
55
  */
52
56
  watch(conn: SQLiteConnection, table: string): Promise<void>;
57
+ private watchNow;
53
58
  /**
54
59
  * Drops a table's change-capture triggers and removes the table from the watched set.
55
60
  *
56
61
  * @param conn - The writer connection on which the tracker drops the triggers.
57
- * @param table - The name of the table to stop watching.
62
+ * @param table - The name of the table to stop watching, in any letter case.
58
63
  */
59
64
  unwatch(conn: SQLiteConnection, table: string): Promise<void>;
65
+ /**
66
+ * Returns the stored name of the watched table that a name refers to, ignoring the case of ASCII letters as SQLite does.
67
+ *
68
+ * @param table - The name to look up.
69
+ * @returns The stored name, or `undefined` when the tracker watches no such table.
70
+ * @internal
71
+ */
72
+ watchedTableNamed(table: string): string | undefined;
60
73
  /**
61
74
  * Rebuilds the change-capture triggers on `conn` for every watched table
62
- * whose column list has changed, without opening a nested transaction.
75
+ * whose columns or unique keys have changed, without opening a nested transaction.
63
76
  *
64
77
  * Call it after a DDL statement inside an open transaction, so that the next
65
78
  * write in that transaction records the new columns in `new_data`. You can
@@ -70,9 +83,11 @@ declare class ChangeTracker {
70
83
  * driver error or an invalid column name propagates to the caller, so that
71
84
  * the caller can roll back its transaction.
72
85
  *
86
+ * @param conn - The writer connection, which can hold an open transaction.
87
+ * @param rebuilt - The watched tables whose triggers the caller dropped, which the method installs again whether or not their shape changed.
73
88
  * @internal
74
89
  */
75
- refreshAllTriggersUsingConnection(conn: SQLiteConnection): Promise<void>;
90
+ refreshAllTriggersUsingConnection(conn: SQLiteConnection, rebuilt?: ReadonlySet<string>): Promise<void>;
76
91
  /**
77
92
  * Drops the change-capture triggers of each named table that the tracker
78
93
  * watches, and removes that table from the watched set.
@@ -122,7 +137,9 @@ declare class ChangeTracker {
122
137
  private assertIdentifier;
123
138
  private detectChangesTable;
124
139
  private ensureChangesTable;
125
- private installTriggers;
140
+ private readShape;
141
+ private markWatched;
142
+ private markUnwatched;
126
143
  }
127
144
 
128
- export { ChangeTracker as C, type ChangeTrackerOptions as a };
145
+ export { ChangeTracker as C, type PruneBoundarySource as P, type ChangeTrackerOptions as a };
@@ -13,7 +13,7 @@ function toColumnValue(value) {
13
13
  return { intValue: value };
14
14
  }
15
15
  if (typeof value === "number") {
16
- if (Number.isInteger(value)) {
16
+ if (Number.isSafeInteger(value)) {
17
17
  return { intValue: BigInt(value) };
18
18
  }
19
19
  return { floatValue: value };
@@ -91,7 +91,8 @@ function toBatchPayload(batch) {
91
91
  changes: batch.changes.map(toProtoChange),
92
92
  checksum: batch.checksum,
93
93
  groupId: batch.groupId ?? "",
94
- primaryTerm: batch.primaryTerm ?? 0n
94
+ primaryTerm: batch.primaryTerm ?? 0n,
95
+ afterSeq: batch.afterSeq ?? 0n
95
96
  };
96
97
  }
97
98
  function fromBatchPayload(payload) {
@@ -107,7 +108,8 @@ function fromBatchPayload(payload) {
107
108
  changes: payload.changes.map(fromProtoChange),
108
109
  checksum: payload.checksum,
109
110
  groupId: payload.groupId || void 0,
110
- primaryTerm: payload.primaryTerm === 0n ? void 0 : payload.primaryTerm
111
+ primaryTerm: payload.primaryTerm === 0n ? void 0 : payload.primaryTerm,
112
+ afterSeq: payload.afterSeq === 0n ? void 0 : payload.afterSeq
111
113
  };
112
114
  }
113
115
  function toAckPayload(ack) {
@@ -135,7 +137,8 @@ function toSyncRequestPayload(req) {
135
137
  completedTables: req.completedTables,
136
138
  groupId: req.groupId ?? "",
137
139
  primaryTerm: req.primaryTerm ?? 0n,
138
- supportsStreamVerification: req.supportsStreamVerification === true
140
+ supportsStreamVerification: req.supportsStreamVerification === true,
141
+ historyTail: req.historyTail ? { hlc: req.historyTail.hlc, txId: req.historyTail.txId } : void 0
139
142
  };
140
143
  }
141
144
  function fromSyncRequestPayload(p) {
@@ -145,7 +148,8 @@ function fromSyncRequestPayload(p) {
145
148
  completedTables: p.completedTables,
146
149
  supportsStreamVerification: p.supportsStreamVerification === true ? true : void 0,
147
150
  groupId: p.groupId || void 0,
148
- primaryTerm: p.primaryTerm === 0n ? void 0 : p.primaryTerm
151
+ primaryTerm: p.primaryTerm === 0n ? void 0 : p.primaryTerm,
152
+ historyTail: p.historyTail ? { hlc: p.historyTail.hlc, txId: p.historyTail.txId } : void 0
149
153
  };
150
154
  }
151
155
  function toSyncBatchPayload(batch) {
@@ -187,7 +191,9 @@ function toSyncCompletePayload(complete) {
187
191
  batchDigest: m.batchDigest ?? ""
188
192
  })),
189
193
  groupId: complete.groupId ?? "",
190
- primaryTerm: complete.primaryTerm ?? 0n
194
+ primaryTerm: complete.primaryTerm ?? 0n,
195
+ historyPoint: complete.historyPoint ? { hlc: complete.historyPoint.hlc, txId: complete.historyPoint.txId } : void 0,
196
+ resumed: complete.resumed === true
191
197
  };
192
198
  }
193
199
  function fromSyncCompletePayload(p) {
@@ -203,7 +209,9 @@ function fromSyncCompletePayload(p) {
203
209
  })
204
210
  ),
205
211
  groupId: p.groupId || void 0,
206
- primaryTerm: p.primaryTerm === 0n ? void 0 : p.primaryTerm
212
+ primaryTerm: p.primaryTerm === 0n ? void 0 : p.primaryTerm,
213
+ historyPoint: p.historyPoint ? { hlc: p.historyPoint.hlc, txId: p.historyPoint.txId } : void 0,
214
+ resumed: p.resumed === true ? true : void 0
207
215
  };
208
216
  }
209
217
  function toSyncAckPayload(ack) {
@@ -0,0 +1,55 @@
1
+ import { withRowCounts, rowCountsOf } from './chunk-E2GRX4ZD.mjs';
2
+ import { SirannonError } from './chunk-KINDFBQP.mjs';
3
+
4
+ // src/core/worker/protocol.ts
5
+ function toWorkerGroupStatement(statement) {
6
+ return {
7
+ sql: statement.sql,
8
+ params: statement.params ? [...statement.params] : [],
9
+ ...statement.trusted === true ? { trusted: true } : {}
10
+ };
11
+ }
12
+ var WORKER_CANCELLED_CODE = "WRITER_WORKER_CANCELLED";
13
+ var WORKER_BEGIN_FAILED_CODE = "WRITER_WORKER_BEGIN_FAILED";
14
+ var KINDS_THAT_CARRY_BEGIN = /* @__PURE__ */ new Set([
15
+ "exec",
16
+ "run",
17
+ "get",
18
+ "all",
19
+ "allRaw",
20
+ "allCounted",
21
+ "getCounted",
22
+ "allRawCounted",
23
+ "runBatch",
24
+ "runBatchSummary"
25
+ ]);
26
+ function canCarryBegin(kind) {
27
+ return KINDS_THAT_CARRY_BEGIN.has(kind);
28
+ }
29
+ function leftTransactionUnbegun(error) {
30
+ return error.code === WORKER_BEGIN_FAILED_CODE || error.code === WORKER_CANCELLED_CODE;
31
+ }
32
+ var WORKER_COPY_STOPPED_CODE = "WRITER_WORKER_COPY_STOPPED";
33
+ function serializeError(err) {
34
+ if (err instanceof Error) {
35
+ const { code, sql } = err;
36
+ return withRowCounts(
37
+ {
38
+ message: err.message,
39
+ name: err.name,
40
+ ...typeof code === "string" ? { code } : {},
41
+ ...typeof sql === "string" ? { sql } : {},
42
+ ...err instanceof SirannonError ? { sirannonError: true } : {}
43
+ },
44
+ rowCountsOf(err)
45
+ );
46
+ }
47
+ return { message: String(err) };
48
+ }
49
+ function deserializeError(error) {
50
+ const err = error.sirannonError === true && error.code !== void 0 ? new SirannonError(error.message, error.code) : Object.assign(new Error(error.message), error.code === void 0 ? {} : { code: error.code });
51
+ if (error.name) err.name = error.name;
52
+ return withRowCounts(err, rowCountsOf(error));
53
+ }
54
+
55
+ export { WORKER_BEGIN_FAILED_CODE, WORKER_CANCELLED_CODE, WORKER_COPY_STOPPED_CODE, canCarryBegin, deserializeError, leftTransactionUnbegun, serializeError, toWorkerGroupStatement };
@@ -1,8 +1,9 @@
1
- import { LOG_HEADER_BYTES, readLogHeader, logFrameOffset, readValidLogFrame } from './chunk-R7GBXNTO.mjs';
1
+ import { LOG_HEADER_BYTES, readLogHeader, logFrameOffset, readValidLogFrame } from './chunk-BUWJH3D3.mjs';
2
2
  import { SirannonError } from './chunk-KINDFBQP.mjs';
3
3
  import { open } from 'fs/promises';
4
4
 
5
5
  var READ_CHUNK_BYTES = 4 * 1024 * 1024;
6
+ var LOG_POSITION_READ_ATTEMPTS = 5;
6
7
  async function openForReading(path) {
7
8
  try {
8
9
  return await open(path, "r");
@@ -120,19 +121,27 @@ function logPathFor(sourcePath) {
120
121
  async function readLogPosition(sourcePath) {
121
122
  const logPath = logPathFor(sourcePath);
122
123
  try {
123
- const header = await readLogFileHeader(logPath);
124
- if (!header) return void 0;
125
- const scan = await scanLogFrames(logPath, header, { frame: 0, checksum: header.checksum });
126
- return {
127
- logSequence: header.logSequence,
128
- salt1: header.salt1,
129
- salt2: header.salt2,
130
- lastFrame: scan.lastCommitFrame
131
- };
124
+ for (let attempt = 0; attempt < LOG_POSITION_READ_ATTEMPTS; attempt++) {
125
+ const header = await readLogFileHeader(logPath);
126
+ if (!header) return void 0;
127
+ const scan = await scanLogFrames(logPath, header, { frame: 0, checksum: header.checksum });
128
+ const headerAfterScan = await readLogFileHeader(logPath);
129
+ if (headerAfterScan === void 0 || !sameGeneration(header, headerAfterScan)) continue;
130
+ return {
131
+ logSequence: header.logSequence,
132
+ salt1: header.salt1,
133
+ salt2: header.salt2,
134
+ lastFrame: scan.lastCommitFrame
135
+ };
136
+ }
137
+ return void 0;
132
138
  } catch {
133
139
  return void 0;
134
140
  }
135
141
  }
142
+ function sameGeneration(first, second) {
143
+ return first.logSequence === second.logSequence && first.salt1 === second.salt1 && first.salt2 === second.salt2;
144
+ }
136
145
  function cursorChecksum(cursor) {
137
146
  return { first: cursor.checksum1, second: cursor.checksum2 };
138
147
  }