@earendil-works/pi-durable 0.99.1 → 1.0.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.
Files changed (203) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +557 -46
  3. package/dist/entries.d.ts +20 -2
  4. package/dist/entries.d.ts.map +1 -1
  5. package/dist/entries.js +14 -1
  6. package/dist/entries.js.map +1 -1
  7. package/dist/env/index.d.ts +18 -38
  8. package/dist/env/index.d.ts.map +1 -1
  9. package/dist/env/index.js +2 -0
  10. package/dist/env/index.js.map +1 -1
  11. package/dist/env/node.d.ts +2 -0
  12. package/dist/env/node.d.ts.map +1 -1
  13. package/dist/env/node.js +53 -58
  14. package/dist/env/node.js.map +1 -1
  15. package/dist/harness/agent.d.ts +31 -0
  16. package/dist/harness/agent.d.ts.map +1 -0
  17. package/dist/harness/agent.js +209 -0
  18. package/dist/harness/agent.js.map +1 -0
  19. package/dist/harness/compaction.d.ts +56 -0
  20. package/dist/harness/compaction.d.ts.map +1 -0
  21. package/dist/harness/compaction.js +382 -0
  22. package/dist/harness/compaction.js.map +1 -0
  23. package/dist/harness/context.d.ts +8 -0
  24. package/dist/harness/context.d.ts.map +1 -1
  25. package/dist/harness/context.js +32 -21
  26. package/dist/harness/context.js.map +1 -1
  27. package/dist/harness/define.d.ts +18 -0
  28. package/dist/harness/define.d.ts.map +1 -0
  29. package/dist/harness/define.js +25 -0
  30. package/dist/harness/define.js.map +1 -0
  31. package/dist/harness/events.d.ts +166 -0
  32. package/dist/harness/events.d.ts.map +1 -0
  33. package/dist/harness/events.js +319 -0
  34. package/dist/harness/events.js.map +1 -0
  35. package/dist/harness/generation.d.ts +36 -7
  36. package/dist/harness/generation.d.ts.map +1 -1
  37. package/dist/harness/generation.js +356 -82
  38. package/dist/harness/generation.js.map +1 -1
  39. package/dist/harness/harness.d.ts.map +1 -1
  40. package/dist/harness/harness.js +141 -106
  41. package/dist/harness/harness.js.map +1 -1
  42. package/dist/harness/inbox.d.ts +59 -0
  43. package/dist/harness/inbox.d.ts.map +1 -0
  44. package/dist/harness/inbox.js +97 -0
  45. package/dist/harness/inbox.js.map +1 -0
  46. package/dist/harness/json.d.ts +10 -0
  47. package/dist/harness/json.d.ts.map +1 -0
  48. package/dist/harness/json.js +33 -0
  49. package/dist/harness/json.js.map +1 -0
  50. package/dist/harness/live.d.ts +66 -7
  51. package/dist/harness/live.d.ts.map +1 -1
  52. package/dist/harness/live.js +71 -7
  53. package/dist/harness/live.js.map +1 -1
  54. package/dist/harness/output.d.ts +62 -0
  55. package/dist/harness/output.d.ts.map +1 -0
  56. package/dist/harness/output.js +261 -0
  57. package/dist/harness/output.js.map +1 -0
  58. package/dist/harness/prompt.d.ts +9 -6
  59. package/dist/harness/prompt.d.ts.map +1 -1
  60. package/dist/harness/prompt.js +57 -14
  61. package/dist/harness/prompt.js.map +1 -1
  62. package/dist/harness/registry.d.ts +2 -3
  63. package/dist/harness/registry.d.ts.map +1 -1
  64. package/dist/harness/registry.js +69 -277
  65. package/dist/harness/registry.js.map +1 -1
  66. package/dist/harness/scheduler.d.ts +42 -12
  67. package/dist/harness/scheduler.d.ts.map +1 -1
  68. package/dist/harness/scheduler.js +649 -75
  69. package/dist/harness/scheduler.js.map +1 -1
  70. package/dist/harness/submissions.d.ts +14 -9
  71. package/dist/harness/submissions.d.ts.map +1 -1
  72. package/dist/harness/submissions.js +76 -34
  73. package/dist/harness/submissions.js.map +1 -1
  74. package/dist/harness/task-graph.d.ts +49 -0
  75. package/dist/harness/task-graph.d.ts.map +1 -0
  76. package/dist/harness/task-graph.js +163 -0
  77. package/dist/harness/task-graph.js.map +1 -0
  78. package/dist/harness/tool.d.ts +36 -0
  79. package/dist/harness/tool.d.ts.map +1 -0
  80. package/dist/harness/tool.js +415 -0
  81. package/dist/harness/tool.js.map +1 -0
  82. package/dist/harness/types.d.ts +330 -125
  83. package/dist/harness/types.d.ts.map +1 -1
  84. package/dist/harness/types.js.map +1 -1
  85. package/dist/harness/usage.d.ts +18 -0
  86. package/dist/harness/usage.d.ts.map +1 -0
  87. package/dist/harness/usage.js +57 -0
  88. package/dist/harness/usage.js.map +1 -0
  89. package/dist/harness/view.d.ts +43 -0
  90. package/dist/harness/view.d.ts.map +1 -0
  91. package/dist/harness/view.js +189 -0
  92. package/dist/harness/view.js.map +1 -0
  93. package/dist/index.d.ts +13 -5
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +8 -2
  96. package/dist/index.js.map +1 -1
  97. package/dist/session/observation.d.ts +18 -11
  98. package/dist/session/observation.d.ts.map +1 -1
  99. package/dist/session/observation.js +24 -13
  100. package/dist/session/observation.js.map +1 -1
  101. package/dist/session/session.d.ts +10 -1
  102. package/dist/session/session.d.ts.map +1 -1
  103. package/dist/session/session.js +23 -5
  104. package/dist/session/session.js.map +1 -1
  105. package/dist/session/transaction.d.ts +12 -3
  106. package/dist/session/transaction.d.ts.map +1 -1
  107. package/dist/session/transaction.js +90 -31
  108. package/dist/session/transaction.js.map +1 -1
  109. package/dist/storage/jsonl/storage.d.ts +22 -2
  110. package/dist/storage/jsonl/storage.d.ts.map +1 -1
  111. package/dist/storage/jsonl/storage.js +1 -1
  112. package/dist/storage/jsonl/storage.js.map +1 -1
  113. package/dist/storage/memory.js +1 -1
  114. package/dist/storage/memory.js.map +1 -1
  115. package/dist/storage/sqlite/database.d.ts +26 -19
  116. package/dist/storage/sqlite/database.d.ts.map +1 -1
  117. package/dist/storage/sqlite/database.js.map +1 -1
  118. package/dist/storage/sqlite/index.d.ts +1 -1
  119. package/dist/storage/sqlite/index.d.ts.map +1 -1
  120. package/dist/storage/sqlite/index.js.map +1 -1
  121. package/dist/storage/sqlite/migrations.js +7 -7
  122. package/dist/storage/sqlite/migrations.js.map +1 -1
  123. package/dist/storage/sqlite/node.d.ts +23 -7
  124. package/dist/storage/sqlite/node.d.ts.map +1 -1
  125. package/dist/storage/sqlite/node.js +129 -47
  126. package/dist/storage/sqlite/node.js.map +1 -1
  127. package/dist/storage/sqlite/storage.d.ts +12 -0
  128. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  129. package/dist/storage/sqlite/storage.js +121 -129
  130. package/dist/storage/sqlite/storage.js.map +1 -1
  131. package/dist/testing/storage-benchmark.d.ts.map +1 -1
  132. package/dist/testing/storage-benchmark.js +0 -1
  133. package/dist/testing/storage-benchmark.js.map +1 -1
  134. package/dist/testing/storage-conformance.d.ts.map +1 -1
  135. package/dist/testing/storage-conformance.js +34 -2
  136. package/dist/testing/storage-conformance.js.map +1 -1
  137. package/dist/tools/bash.d.ts +28 -0
  138. package/dist/tools/bash.d.ts.map +1 -0
  139. package/dist/tools/bash.js +70 -0
  140. package/dist/tools/bash.js.map +1 -0
  141. package/dist/tools/edit-diff.d.ts +89 -0
  142. package/dist/tools/edit-diff.d.ts.map +1 -0
  143. package/dist/tools/edit-diff.js +386 -0
  144. package/dist/tools/edit-diff.js.map +1 -0
  145. package/dist/tools/edit.d.ts +18 -0
  146. package/dist/tools/edit.d.ts.map +1 -0
  147. package/dist/tools/edit.js +117 -0
  148. package/dist/tools/edit.js.map +1 -0
  149. package/dist/tools/env.d.ts +5 -0
  150. package/dist/tools/env.d.ts.map +1 -0
  151. package/dist/tools/env.js +7 -0
  152. package/dist/tools/env.js.map +1 -0
  153. package/dist/tools/file-mutation-queue.d.ts +9 -0
  154. package/dist/tools/file-mutation-queue.d.ts.map +1 -0
  155. package/dist/tools/file-mutation-queue.js +52 -0
  156. package/dist/tools/file-mutation-queue.js.map +1 -0
  157. package/dist/tools/image.d.ts +2 -0
  158. package/dist/tools/image.d.ts.map +1 -0
  159. package/dist/tools/image.js +92 -0
  160. package/dist/tools/image.js.map +1 -0
  161. package/dist/tools/index.d.ts +23 -0
  162. package/dist/tools/index.d.ts.map +1 -0
  163. package/dist/tools/index.js +15 -0
  164. package/dist/tools/index.js.map +1 -0
  165. package/dist/tools/path-utils.d.ts +5 -0
  166. package/dist/tools/path-utils.d.ts.map +1 -0
  167. package/dist/tools/path-utils.js +26 -0
  168. package/dist/tools/path-utils.js.map +1 -0
  169. package/dist/tools/read.d.ts +17 -0
  170. package/dist/tools/read.d.ts.map +1 -0
  171. package/dist/tools/read.js +101 -0
  172. package/dist/tools/read.js.map +1 -0
  173. package/dist/tools/write.d.ts +10 -0
  174. package/dist/tools/write.d.ts.map +1 -0
  175. package/dist/tools/write.js +31 -0
  176. package/dist/tools/write.js.map +1 -0
  177. package/dist/{env/utils/truncate.d.ts → truncate.d.ts} +1 -17
  178. package/dist/truncate.d.ts.map +1 -0
  179. package/dist/truncate.js +146 -0
  180. package/dist/truncate.js.map +1 -0
  181. package/dist/types.d.ts +97 -19
  182. package/dist/types.d.ts.map +1 -1
  183. package/dist/types.js.map +1 -1
  184. package/package.json +32 -14
  185. package/dist/env/utils/adaptive-publisher.d.ts +0 -24
  186. package/dist/env/utils/adaptive-publisher.d.ts.map +0 -1
  187. package/dist/env/utils/adaptive-publisher.js +0 -79
  188. package/dist/env/utils/adaptive-publisher.js.map +0 -1
  189. package/dist/env/utils/output-capture.d.ts +0 -31
  190. package/dist/env/utils/output-capture.d.ts.map +0 -1
  191. package/dist/env/utils/output-capture.js +0 -238
  192. package/dist/env/utils/output-capture.js.map +0 -1
  193. package/dist/env/utils/truncate.d.ts.map +0 -1
  194. package/dist/env/utils/truncate.js +0 -294
  195. package/dist/env/utils/truncate.js.map +0 -1
  196. package/dist/harness/config.d.ts +0 -20
  197. package/dist/harness/config.d.ts.map +0 -1
  198. package/dist/harness/config.js +0 -18
  199. package/dist/harness/config.js.map +0 -1
  200. package/docs/chord-delta-findings.md +0 -358
  201. package/docs/pico-v5-chord-usage.md +0 -373
  202. package/docs/pico-v5-handoff.md +0 -581
  203. package/docs/pico-v5.md +0 -3084
@@ -4,66 +4,148 @@ import { DatabaseSync } from "node:sqlite";
4
4
  import { SqliteStorage } from "./storage.js";
5
5
  const DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;
6
6
  const DEFAULT_BUSY_TIMEOUT_MS = 5_000;
7
- class NodeSqliteStatement {
8
- statement;
9
- constructor(statement) {
10
- this.statement = statement;
7
+ const ignore = () => { };
8
+ /**
9
+ * Runs operations in call order. An operation starts immediately when nothing is running or waiting;
10
+ * otherwise it waits for everything before it. An asynchronous operation holds the queue until it settles.
11
+ */
12
+ class SerialOperationQueue {
13
+ tail = Promise.resolve();
14
+ pending = 0;
15
+ run(operation) {
16
+ if (this.pending > 0)
17
+ return this.enqueue(operation);
18
+ try {
19
+ return Promise.resolve(operation());
20
+ }
21
+ catch (error) {
22
+ return Promise.reject(error);
23
+ }
11
24
  }
12
- run(...params) {
13
- this.statement.run(...params);
25
+ runAsync(operation) {
26
+ if (this.pending > 0)
27
+ return this.enqueue(operation);
28
+ this.pending++;
29
+ // Publish the barrier before the operation starts, so calls it makes synchronously wait behind it.
30
+ const { promise: barrier, resolve: releaseBarrier } = Promise.withResolvers();
31
+ this.tail = barrier;
32
+ let started;
33
+ try {
34
+ started = operation();
35
+ }
36
+ catch (error) {
37
+ started = Promise.reject(error);
38
+ }
39
+ return started.finally(() => {
40
+ this.pending--;
41
+ releaseBarrier();
42
+ });
14
43
  }
15
- get(...params) {
16
- return this.statement.get(...params);
44
+ enqueue(operation) {
45
+ this.pending++;
46
+ return this.release(this.tail.then(operation));
17
47
  }
18
- all(...params) {
19
- return this.statement.all(...params);
48
+ release(operation) {
49
+ const settled = operation.finally(() => {
50
+ this.pending--;
51
+ });
52
+ this.tail = settled.then(ignore, ignore);
53
+ return settled;
20
54
  }
21
55
  }
22
- /** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */
23
- export class NodeSqliteDatabase {
56
+ /**
57
+ * Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the
58
+ * database and its transaction handles share them across transactions.
59
+ */
60
+ class NodeSqliteExecutor {
24
61
  database;
25
- closed = false;
26
- constructor(database) {
62
+ statements;
63
+ constructor(database, statements) {
27
64
  this.database = database;
65
+ this.statements = statements;
28
66
  }
29
67
  exec(sql) {
30
- this.database.exec(sql);
68
+ return this.runOperation(() => {
69
+ this.database.exec(sql);
70
+ });
31
71
  }
32
- prepare(sql) {
33
- return new NodeSqliteStatement(this.database.prepare(sql));
72
+ run(sql, ...params) {
73
+ return this.runOperation(() => {
74
+ this.statement(sql).run(...params);
75
+ });
34
76
  }
35
- transaction(callback) {
36
- this.database.exec("BEGIN IMMEDIATE");
37
- try {
38
- const result = callback();
39
- if (result !== null &&
40
- (typeof result === "object" || typeof result === "function") &&
41
- typeof Reflect.get(result, "then") === "function") {
42
- throw new TypeError("SQLite transaction callbacks must be synchronous");
43
- }
44
- this.database.exec("COMMIT");
45
- return result;
77
+ get(sql, ...params) {
78
+ return this.runOperation(() => this.statement(sql).get(...params));
79
+ }
80
+ all(sql, ...params) {
81
+ return this.runOperation(() => this.statement(sql).all(...params));
82
+ }
83
+ statement(sql) {
84
+ let statement = this.statements.get(sql);
85
+ if (statement === undefined) {
86
+ statement = this.database.prepare(sql);
87
+ this.statements.set(sql, statement);
46
88
  }
47
- catch (error) {
89
+ return statement;
90
+ }
91
+ }
92
+ class NodeSqliteTransaction extends NodeSqliteExecutor {
93
+ scope;
94
+ constructor(database, statements, scope) {
95
+ super(database, statements);
96
+ this.scope = scope;
97
+ }
98
+ async runOperation(operation) {
99
+ if (!this.scope.active)
100
+ throw new Error("SQLite transaction handle is no longer active");
101
+ return operation();
102
+ }
103
+ }
104
+ /** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */
105
+ export class NodeSqliteDatabase extends NodeSqliteExecutor {
106
+ access = new SerialOperationQueue();
107
+ closed = false;
108
+ constructor(database) {
109
+ super(database, new Map());
110
+ }
111
+ transaction(callback) {
112
+ return this.access.runAsync(async () => {
113
+ this.database.exec("BEGIN IMMEDIATE");
114
+ const scope = { active: true };
48
115
  try {
49
- this.database.exec("ROLLBACK");
116
+ const result = await callback(new NodeSqliteTransaction(this.database, this.statements, scope));
117
+ scope.active = false;
118
+ this.database.exec("COMMIT");
119
+ return result;
50
120
  }
51
- catch (rollbackError) {
52
- throw new AggregateError([error, rollbackError], "SQLite transaction failed and rollback failed");
121
+ catch (error) {
122
+ scope.active = false;
123
+ try {
124
+ this.database.exec("ROLLBACK");
125
+ }
126
+ catch (rollbackError) {
127
+ throw new AggregateError([error, rollbackError], "SQLite transaction failed and rollback failed");
128
+ }
129
+ throw error;
53
130
  }
54
- throw error;
55
- }
131
+ });
56
132
  }
57
133
  close() {
58
- if (this.closed)
59
- return;
60
- this.closed = true;
61
- try {
62
- this.database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
63
- }
64
- finally {
65
- this.database.close();
66
- }
134
+ return this.access.run(() => {
135
+ if (this.closed)
136
+ return;
137
+ this.closed = true;
138
+ this.statements.clear();
139
+ try {
140
+ this.database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
141
+ }
142
+ finally {
143
+ this.database.close();
144
+ }
145
+ });
146
+ }
147
+ runOperation(operation) {
148
+ return this.access.run(operation);
67
149
  }
68
150
  }
69
151
  /** Open and configure a Node-backed SQLite database facade. */
@@ -75,14 +157,14 @@ export async function openNodeSqliteDatabase(path, options = {}) {
75
157
  const database = new DatabaseSync(path, { timeout });
76
158
  const adapter = new NodeSqliteDatabase(database);
77
159
  try {
78
- adapter.exec("PRAGMA journal_mode = WAL");
79
- adapter.exec("PRAGMA synchronous = NORMAL");
80
- adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);
160
+ await adapter.exec("PRAGMA journal_mode = WAL");
161
+ await adapter.exec("PRAGMA synchronous = NORMAL");
162
+ await adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);
81
163
  return adapter;
82
164
  }
83
165
  catch (error) {
84
166
  try {
85
- adapter.close();
167
+ await adapter.close();
86
168
  }
87
169
  catch {
88
170
  // Preserve the configuration failure.
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { SQLInputValue, StatementSync } from \"node:sqlite\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteStatement, SqliteValue } from \"./database.ts\";\nimport { SqliteStorage } from \"./storage.ts\";\n\n/** Node SQLite connection settings for a durable storage file. */\nexport type NodeSqliteStorageOptions = {\n\t/** SQLite WAL auto-checkpoint threshold. SQLite and this adapter default to 1,000 pages; 0 disables it. */\n\treadonly walAutoCheckpointPages?: number;\n\t/** Time SQLite waits for a competing file lock. SQLite defaults to 0; this adapter defaults to 5,000 ms. */\n\treadonly busyTimeoutMs?: number;\n};\n\nconst DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;\nconst DEFAULT_BUSY_TIMEOUT_MS = 5_000;\n\nclass NodeSqliteStatement implements SqliteStatement {\n\tprivate readonly statement: StatementSync;\n\n\tconstructor(statement: StatementSync) {\n\t\tthis.statement = statement;\n\t}\n\n\trun(...params: SqliteValue[]): void {\n\t\tthis.statement.run(...(params as SQLInputValue[]));\n\t}\n\n\tget<T extends object>(...params: SqliteValue[]): T | undefined {\n\t\treturn this.statement.get(...(params as SQLInputValue[])) as T | undefined;\n\t}\n\n\tall<T extends object>(...params: SqliteValue[]): T[] {\n\t\treturn this.statement.all(...(params as SQLInputValue[])) as T[];\n\t}\n}\n\n/** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */\nexport class NodeSqliteDatabase implements SqliteDatabase {\n\tprivate readonly database: DatabaseSync;\n\tprivate closed = false;\n\n\tconstructor(database: DatabaseSync) {\n\t\tthis.database = database;\n\t}\n\n\texec(sql: string): void {\n\t\tthis.database.exec(sql);\n\t}\n\n\tprepare(sql: string): SqliteStatement {\n\t\treturn new NodeSqliteStatement(this.database.prepare(sql));\n\t}\n\n\ttransaction<T>(callback: () => T): T {\n\t\tthis.database.exec(\"BEGIN IMMEDIATE\");\n\t\ttry {\n\t\t\tconst result = callback();\n\t\t\tif (\n\t\t\t\tresult !== null &&\n\t\t\t\t(typeof result === \"object\" || typeof result === \"function\") &&\n\t\t\t\ttypeof Reflect.get(result, \"then\") === \"function\"\n\t\t\t) {\n\t\t\t\tthrow new TypeError(\"SQLite transaction callbacks must be synchronous\");\n\t\t\t}\n\t\t\tthis.database.exec(\"COMMIT\");\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\ttry {\n\t\t\t\tthis.database.exec(\"ROLLBACK\");\n\t\t\t} catch (rollbackError) {\n\t\t\t\tthrow new AggregateError([error, rollbackError], \"SQLite transaction failed and rollback failed\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\ttry {\n\t\t\tthis.database.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n\t\t} finally {\n\t\t\tthis.database.close();\n\t\t}\n\t}\n}\n\n/** Open and configure a Node-backed SQLite database facade. */\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<NodeSqliteDatabase> {\n\tconst checkpointPages = options.walAutoCheckpointPages ?? DEFAULT_WAL_AUTO_CHECKPOINT_PAGES;\n\tconst timeout = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;\n\tif (path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\tconst database = new DatabaseSync(path, { timeout });\n\tconst adapter = new NodeSqliteDatabase(database);\n\ttry {\n\t\tadapter.exec(\"PRAGMA journal_mode = WAL\");\n\t\tadapter.exec(\"PRAGMA synchronous = NORMAL\");\n\t\tadapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);\n\t\treturn adapter;\n\t} catch (error) {\n\t\ttry {\n\t\t\tadapter.close();\n\t\t} catch {\n\t\t\t// Preserve the configuration failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Open or create file-backed durable storage using Node's built-in SQLite. */\nexport async function openNodeSqliteStorage(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<SqliteStorage> {\n\treturn SqliteStorage.open(await openNodeSqliteDatabase(path, options));\n}\n"]}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { StatementSync } from \"node:sqlite\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nimport { SqliteStorage } from \"./storage.ts\";\n\n/** Node SQLite connection settings for a durable storage file. */\nexport type NodeSqliteStorageOptions = {\n\t/** SQLite WAL auto-checkpoint threshold. SQLite and this adapter default to 1,000 pages; 0 disables it. */\n\treadonly walAutoCheckpointPages?: number;\n\t/** Time SQLite waits for a competing file lock. SQLite defaults to 0; this adapter defaults to 5,000 ms. */\n\treadonly busyTimeoutMs?: number;\n};\n\nconst DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;\nconst DEFAULT_BUSY_TIMEOUT_MS = 5_000;\n\ntype TransactionScope = { active: boolean };\n\nconst ignore = (): void => {};\n\n/**\n * Runs operations in call order. An operation starts immediately when nothing is running or waiting;\n * otherwise it waits for everything before it. An asynchronous operation holds the queue until it settles.\n */\nclass SerialOperationQueue {\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate pending = 0;\n\n\trun<T>(operation: () => T): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\ttry {\n\t\t\treturn Promise.resolve(operation());\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\trunAsync<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\tthis.pending++;\n\t\t// Publish the barrier before the operation starts, so calls it makes synchronously wait behind it.\n\t\tconst { promise: barrier, resolve: releaseBarrier } = Promise.withResolvers<void>();\n\t\tthis.tail = barrier;\n\t\tlet started: Promise<T>;\n\t\ttry {\n\t\t\tstarted = operation();\n\t\t} catch (error) {\n\t\t\tstarted = Promise.reject(error);\n\t\t}\n\t\treturn started.finally(() => {\n\t\t\tthis.pending--;\n\t\t\treleaseBarrier();\n\t\t});\n\t}\n\n\tprivate enqueue<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tthis.pending++;\n\t\treturn this.release(this.tail.then(operation));\n\t}\n\n\tprivate release<T>(operation: Promise<T>): Promise<T> {\n\t\tconst settled = operation.finally(() => {\n\t\t\tthis.pending--;\n\t\t});\n\t\tthis.tail = settled.then(ignore, ignore);\n\t\treturn settled;\n\t}\n}\n\n/**\n * Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the\n * database and its transaction handles share them across transactions.\n */\nabstract class NodeSqliteExecutor implements SqliteExecutor {\n\tprotected readonly database: DatabaseSync;\n\tprotected readonly statements: Map<string, StatementSync>;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>) {\n\t\tthis.database = database;\n\t\tthis.statements = statements;\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.database.exec(sql);\n\t\t});\n\t}\n\n\trun(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.statement(sql).run(...params);\n\t\t});\n\t}\n\n\tget<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\treturn this.runOperation(() => this.statement(sql).get(...params) as T | undefined);\n\t}\n\n\tall<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\treturn this.runOperation(() => this.statement(sql).all(...params) as T[]);\n\t}\n\n\tprotected abstract runOperation<T>(operation: () => T): Promise<T>;\n\n\tprivate statement(sql: string): StatementSync {\n\t\tlet statement = this.statements.get(sql);\n\t\tif (statement === undefined) {\n\t\t\tstatement = this.database.prepare(sql);\n\t\t\tthis.statements.set(sql, statement);\n\t\t}\n\t\treturn statement;\n\t}\n}\n\nclass NodeSqliteTransaction extends NodeSqliteExecutor {\n\tprivate readonly scope: TransactionScope;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>, scope: TransactionScope) {\n\t\tsuper(database, statements);\n\t\tthis.scope = scope;\n\t}\n\n\tprotected async runOperation<T>(operation: () => T): Promise<T> {\n\t\tif (!this.scope.active) throw new Error(\"SQLite transaction handle is no longer active\");\n\t\treturn operation();\n\t}\n}\n\n/** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */\nexport class NodeSqliteDatabase extends NodeSqliteExecutor implements SqliteDatabase {\n\tprivate readonly access = new SerialOperationQueue();\n\tprivate closed = false;\n\n\tconstructor(database: DatabaseSync) {\n\t\tsuper(database, new Map());\n\t}\n\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.access.runAsync(async () => {\n\t\t\tthis.database.exec(\"BEGIN IMMEDIATE\");\n\t\t\tconst scope = { active: true };\n\t\t\ttry {\n\t\t\t\tconst result = await callback(new NodeSqliteTransaction(this.database, this.statements, scope));\n\t\t\t\tscope.active = false;\n\t\t\t\tthis.database.exec(\"COMMIT\");\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tscope.active = false;\n\t\t\t\ttry {\n\t\t\t\t\tthis.database.exec(\"ROLLBACK\");\n\t\t\t\t} catch (rollbackError) {\n\t\t\t\t\tthrow new AggregateError([error, rollbackError], \"SQLite transaction failed and rollback failed\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.access.run(() => {\n\t\t\tif (this.closed) return;\n\t\t\tthis.closed = true;\n\t\t\tthis.statements.clear();\n\t\t\ttry {\n\t\t\t\tthis.database.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n\t\t\t} finally {\n\t\t\t\tthis.database.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected runOperation<T>(operation: () => T): Promise<T> {\n\t\treturn this.access.run(operation);\n\t}\n}\n\n/** Open and configure a Node-backed SQLite database facade. */\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<NodeSqliteDatabase> {\n\tconst checkpointPages = options.walAutoCheckpointPages ?? DEFAULT_WAL_AUTO_CHECKPOINT_PAGES;\n\tconst timeout = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;\n\tif (path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\tconst database = new DatabaseSync(path, { timeout });\n\tconst adapter = new NodeSqliteDatabase(database);\n\ttry {\n\t\tawait adapter.exec(\"PRAGMA journal_mode = WAL\");\n\t\tawait adapter.exec(\"PRAGMA synchronous = NORMAL\");\n\t\tawait adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);\n\t\treturn adapter;\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait adapter.close();\n\t\t} catch {\n\t\t\t// Preserve the configuration failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Open or create file-backed durable storage using Node's built-in SQLite. */\nexport async function openNodeSqliteStorage(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<SqliteStorage> {\n\treturn SqliteStorage.open(await openNodeSqliteDatabase(path, options));\n}\n"]}
@@ -7,6 +7,9 @@ export declare class SqliteStorage implements Storage {
7
7
  private readonly db;
8
8
  private nextId;
9
9
  private closed;
10
+ private closing;
11
+ private admittedReads;
12
+ private readsDrained;
10
13
  private constructor();
11
14
  /** Initialize storage over an owned SQLite database facade. */
12
15
  static open(db: SqliteDatabase): Promise<SqliteStorage>;
@@ -26,6 +29,9 @@ export declare class SqliteStorage implements Storage {
26
29
  readonly head: EntryId;
27
30
  }) | undefined>;
28
31
  scanEntries(query: EntryQuery, limit: number, cursor: Cursor | undefined, _context: Context): Promise<Page<EntryRecord, Cursor>>;
32
+ private readEntry;
33
+ private readLatestHeadMarker;
34
+ private readEntries;
29
35
  task(id: TaskId, _context: Context): Promise<StoredTask | undefined>;
30
36
  scanTasks(query: TaskQuery, limit: number, cursor: Cursor | undefined, _context: Context): Promise<Page<StoredTask, Cursor>>;
31
37
  submission(id: SubmissionId, _context: Context): Promise<SubmissionRecord | undefined>;
@@ -35,6 +41,12 @@ export declare class SqliteStorage implements Storage {
35
41
  document(id: DocumentId, at: DocumentPoint, _context: Context): Promise<StoredDocument | undefined>;
36
42
  scanDocuments(query: DocumentQuery, limit: number, cursor: Cursor | undefined, _context: Context): Promise<Page<DocumentRecord, Cursor>>;
37
43
  close(_context: Context): Promise<void>;
44
+ private closeDatabase;
45
+ /**
46
+ * Run a read that issues several queries. Close waits for admitted reads, so their later queries never reach a
47
+ * closed database. Single-query reads and transactions are already ordered before close by the database.
48
+ */
49
+ private admitRead;
38
50
  private readConversation;
39
51
  private materializeDocument;
40
52
  private candidateNextId;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/storage.ts"],"names":[],"mappings":"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"}