@delali/sirannon-db 0.1.7 → 0.2.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/README.md +117 -969
- package/dist/backup-scheduler/index.d.ts +1 -1
- package/dist/backup-scheduler/index.mjs +2 -2
- package/dist/baseline-Br77Fnhb.d.ts +6 -0
- package/dist/{change-tracker-CbmaMO-N.d.ts → change-tracker-DKRVUC3l.d.ts} +5 -8
- package/dist/{chunk-DJLX6CAE.mjs → chunk-4ISB7XMA.mjs} +2 -1
- package/dist/chunk-5NOIGN5Y.mjs +18 -0
- package/dist/chunk-67M7KAH6.mjs +90 -0
- package/dist/{chunk-GEZUUIKV.mjs → chunk-D7LAYTKN.mjs} +5 -2
- package/dist/{chunk-4IGMIJQK.mjs → chunk-EBJXPQQO.mjs} +59 -20
- package/dist/{chunk-BNUTBHHH.mjs → chunk-FHWTZFI4.mjs} +1 -1
- package/dist/chunk-GVCNMPOS.mjs +130 -0
- package/dist/chunk-H237TXZW.mjs +1407 -0
- package/dist/{chunk-HHRMRFFR.mjs → chunk-H6PIVVDN.mjs} +353 -142
- package/dist/chunk-HR5CWTLC.mjs +661 -0
- package/dist/chunk-JU64Y7HM.mjs +299 -0
- package/dist/{chunk-CW6S3WL5.mjs → chunk-JZGINXTN.mjs} +7 -5
- package/dist/{chunk-CJLYFDP5.mjs → chunk-LFZ37BSX.mjs} +1 -1
- package/dist/chunk-LNY2VVHE.mjs +18 -0
- package/dist/chunk-NVQS53NT.mjs +665 -0
- package/dist/{chunk-H5AB6NIR.mjs → chunk-O7SLN3GI.mjs} +2 -15
- package/dist/chunk-OQVZBEBY.mjs +283 -0
- package/dist/{chunk-VLTICJOD.mjs → chunk-PIKHN33N.mjs} +1 -1
- package/dist/chunk-TJF5GZSV.mjs +187 -0
- package/dist/chunk-TUD5CJ76.mjs +126 -0
- package/dist/{chunk-YPYVQJ4C.mjs → chunk-UC3SCMIN.mjs} +9 -1
- package/dist/client/index.d.ts +216 -321
- package/dist/client/index.mjs +1192 -1342
- package/dist/client/topology.d.ts +61 -0
- package/dist/client/topology.mjs +682 -0
- package/dist/client-base-CLWmH5Ln.d.ts +234 -0
- package/dist/codegen/cli.d.ts +2 -0
- package/dist/codegen/cli.mjs +11 -0
- package/dist/codegen/index.d.ts +30 -0
- package/dist/codegen/index.mjs +5 -0
- package/dist/core/index.d.ts +37 -16
- package/dist/core/index.mjs +2322 -298
- package/dist/core/writer-worker.mjs +28 -6
- package/dist/{database-DuGp0Rtr.d.ts → database-BY0L5Q2n.d.ts} +59 -14
- package/dist/driver/better-sqlite3.d.ts +1 -1
- package/dist/driver/better-sqlite3.mjs +6 -6
- package/dist/driver/node.d.ts +1 -1
- package/dist/driver/node.mjs +6 -6
- package/dist/driver/wa-sqlite.d.ts +1 -136
- package/dist/{errors-5Nf5ZAEC.d.ts → errors-Bw5MdNCu.d.ts} +5 -1
- package/dist/file-migrations/index.d.ts +7 -5
- package/dist/file-migrations/index.mjs +42 -37
- package/dist/operation-registry-9DcvxcE5.d.ts +45 -0
- package/dist/primary-wins-DPAm2AKG.d.ts +61 -0
- package/dist/protocol-6KrSq2Hy.d.ts +66 -0
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.mjs +137 -0
- package/dist/replication/coordinator/etcd.d.ts +5 -3
- package/dist/replication/coordinator/etcd.mjs +554 -462
- package/dist/replication/index.d.ts +51 -105
- package/dist/replication/index.mjs +1415 -2061
- package/dist/server/index.d.ts +111 -87
- package/dist/server/index.mjs +1917 -489
- package/dist/server-options-1JHu8pid.d.ts +191 -0
- package/dist/{sirannon-4SspRvP5.d.ts → sirannon-DaQSyhbJ.d.ts} +7 -2
- package/dist/transport/grpc.d.ts +7 -4
- package/dist/transport/grpc.mjs +191 -97
- package/dist/transport/memory.d.ts +5 -134
- package/dist/transport/memory.mjs +3 -1
- package/dist/{types-BsjobKbl.d.ts → types-B7gmEsZW.d.ts} +8 -61
- package/dist/{types-BEu1I_9_.d.ts → types-BsVabqSI.d.ts} +1 -1
- package/dist/types-CL6piSnD.d.ts +43 -0
- package/dist/types-C_D8IhpO.d.ts +60 -0
- package/dist/{types-D_hQW1hr.d.ts → types-zhnRXrsb.d.ts} +55 -165
- package/package.json +44 -6
- package/dist/chunk-TKGHYWQ6.mjs +0 -35
- package/dist/types-D4p4UyDK.d.ts +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as SQLiteConnection, f as BackupScheduleOptions } from '../types-
|
|
1
|
+
import { e as SQLiteConnection, f as BackupScheduleOptions } from '../types-zhnRXrsb.js';
|
|
2
2
|
|
|
3
3
|
declare class BackupManager {
|
|
4
4
|
backup(conn: SQLiteConnection, destPath: string): Promise<void>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { BackupScheduler } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { BackupScheduler } from '../chunk-PIKHN33N.mjs';
|
|
2
|
+
import '../chunk-UC3SCMIN.mjs';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { e as SQLiteConnection,
|
|
1
|
+
import { e as SQLiteConnection, h as ChangeEvent } from './types-zhnRXrsb.js';
|
|
2
2
|
|
|
3
3
|
interface ChangeTrackerOptions {
|
|
4
4
|
retention?: number;
|
|
5
5
|
changesTable?: string;
|
|
6
6
|
pollBatchSize?: number;
|
|
7
|
-
replication?: boolean;
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
declare class ChangeTracker {
|
|
@@ -13,11 +12,12 @@ declare class ChangeTracker {
|
|
|
13
12
|
private readonly retentionMs;
|
|
14
13
|
private readonly changesTable;
|
|
15
14
|
private readonly pollBatchSize;
|
|
16
|
-
private readonly replication;
|
|
17
15
|
private changesTableReady;
|
|
16
|
+
private changesTableEnsured;
|
|
18
17
|
private watchedTablesCache;
|
|
19
18
|
private readonly stmtCache;
|
|
20
19
|
private pruneBoundary;
|
|
20
|
+
private lastPollAtTxBoundary;
|
|
21
21
|
constructor(options?: ChangeTrackerOptions);
|
|
22
22
|
watch(conn: SQLiteConnection, table: string): Promise<void>;
|
|
23
23
|
unwatch(conn: SQLiteConnection, table: string): Promise<void>;
|
|
@@ -69,6 +69,7 @@ declare class ChangeTracker {
|
|
|
69
69
|
*/
|
|
70
70
|
pruneDroppedTables(conn: SQLiteConnection, tables: readonly string[]): Promise<void>;
|
|
71
71
|
poll(conn: SQLiteConnection): Promise<ChangeEvent[]>;
|
|
72
|
+
get pollEndedAtTxBoundary(): boolean;
|
|
72
73
|
/** The highest seq already polled; live subscribers receive events beyond it. */
|
|
73
74
|
get cursor(): bigint;
|
|
74
75
|
/**
|
|
@@ -77,9 +78,9 @@ declare class ChangeTracker {
|
|
|
77
78
|
* resuming subscriber without disturbing the shared poll cursor.
|
|
78
79
|
*/
|
|
79
80
|
readSince(conn: SQLiteConnection, table: string, afterSeq: bigint, upToSeq: bigint, limit: number): Promise<ChangeEvent[]>;
|
|
81
|
+
readSinceTables(conn: SQLiteConnection, tables: readonly string[], afterSeq: bigint, upToSeq: bigint, limit: number): Promise<ChangeEvent[]>;
|
|
80
82
|
/** The lowest retained seq, or `null` when the change log is empty. */
|
|
81
83
|
getMinSeq(conn: SQLiteConnection): Promise<bigint | null>;
|
|
82
|
-
private rowToEvent;
|
|
83
84
|
advanceToLatest(conn: SQLiteConnection): Promise<void>;
|
|
84
85
|
cleanup(conn: SQLiteConnection): Promise<number>;
|
|
85
86
|
setPruneBoundary(seq: bigint): void;
|
|
@@ -89,10 +90,6 @@ declare class ChangeTracker {
|
|
|
89
90
|
private assertIdentifier;
|
|
90
91
|
private detectChangesTable;
|
|
91
92
|
private ensureChangesTable;
|
|
92
|
-
private getColumns;
|
|
93
|
-
private getPkColumns;
|
|
94
|
-
private dropTriggers;
|
|
95
|
-
private getStmt;
|
|
96
93
|
private installTriggers;
|
|
97
94
|
}
|
|
98
95
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/core/worker/protocol.ts
|
|
2
|
+
var WORKER_CANCELLED_CODE = "WRITER_WORKER_CANCELLED";
|
|
2
3
|
function serializeError(err) {
|
|
3
4
|
if (err instanceof Error) {
|
|
4
5
|
const code = err.code;
|
|
@@ -17,4 +18,4 @@ function deserializeError(error) {
|
|
|
17
18
|
return err;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export { deserializeError, serializeError };
|
|
21
|
+
export { WORKER_CANCELLED_CODE, deserializeError, serializeError };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SirannonError } from './chunk-UC3SCMIN.mjs';
|
|
2
|
+
|
|
3
|
+
// src/core/sync/errors.ts
|
|
4
|
+
var ReplicationError = class extends SirannonError {
|
|
5
|
+
constructor(message, code = "REPLICATION_ERROR", details) {
|
|
6
|
+
super(message, code);
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "ReplicationError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var BatchValidationError = class extends ReplicationError {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message, "BATCH_VALIDATION_ERROR");
|
|
14
|
+
this.name = "BatchValidationError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { BatchValidationError, ReplicationError };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { MigrationError } from './chunk-UC3SCMIN.mjs';
|
|
2
|
+
|
|
3
|
+
// src/core/migrations/baseline.ts
|
|
4
|
+
var SQLITE_USER_VERSION_MAX = 2147483647;
|
|
5
|
+
function resolveEffectiveBaseline(sorted) {
|
|
6
|
+
const baselines = [];
|
|
7
|
+
for (const migration of sorted) {
|
|
8
|
+
const baseline = migration.baseline;
|
|
9
|
+
if (baseline === void 0) continue;
|
|
10
|
+
if (!Number.isSafeInteger(baseline.through) || baseline.through < 1) {
|
|
11
|
+
throw new MigrationError(
|
|
12
|
+
`Baseline migration ${migration.version}_${migration.name} has an invalid through version: ${baseline.through}`,
|
|
13
|
+
migration.version,
|
|
14
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (baseline.through >= migration.version) {
|
|
18
|
+
throw new MigrationError(
|
|
19
|
+
`Baseline migration ${migration.version}_${migration.name} must use a version above the history it supersedes (through ${baseline.through})`,
|
|
20
|
+
migration.version,
|
|
21
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
baselines.push(migration);
|
|
25
|
+
}
|
|
26
|
+
if (baselines.length === 0) return void 0;
|
|
27
|
+
for (const baseline of baselines) {
|
|
28
|
+
const through = baseline.baseline;
|
|
29
|
+
if (through === void 0) continue;
|
|
30
|
+
for (const migration of sorted) {
|
|
31
|
+
if (migration === baseline) continue;
|
|
32
|
+
if (migration.version > through.through && migration.version < baseline.version) {
|
|
33
|
+
throw new MigrationError(
|
|
34
|
+
`Migration ${migration.version}_${migration.name} falls inside baseline ${baseline.version}_${baseline.name}'s superseded range (above ${through.through}, below ${baseline.version})`,
|
|
35
|
+
migration.version,
|
|
36
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return baselines[baselines.length - 1];
|
|
42
|
+
}
|
|
43
|
+
function applyBaselineOption(migrations, baseline) {
|
|
44
|
+
if (baseline === void 0) return migrations;
|
|
45
|
+
const target = migrations.find((m) => m.version === baseline.version);
|
|
46
|
+
if (target === void 0) {
|
|
47
|
+
throw new MigrationError(
|
|
48
|
+
`Baseline version ${baseline.version} does not match any migration in the set`,
|
|
49
|
+
baseline.version,
|
|
50
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
target.baseline = { through: baseline.through };
|
|
54
|
+
return migrations;
|
|
55
|
+
}
|
|
56
|
+
function planPendingMigrations(sorted, effectiveBaseline, appliedVersions) {
|
|
57
|
+
const baseline = effectiveBaseline?.baseline;
|
|
58
|
+
if (effectiveBaseline === void 0 || baseline === void 0) {
|
|
59
|
+
return sorted.filter((m) => !appliedVersions.has(m.version));
|
|
60
|
+
}
|
|
61
|
+
const through = baseline.through;
|
|
62
|
+
if (appliedVersions.size === 0) {
|
|
63
|
+
return [effectiveBaseline, ...sorted.filter((m) => m.baseline === void 0 && m.version > through)];
|
|
64
|
+
}
|
|
65
|
+
if (appliedVersions.has(effectiveBaseline.version)) {
|
|
66
|
+
return sorted.filter((m) => m.baseline === void 0 && m.version > through && !appliedVersions.has(m.version));
|
|
67
|
+
}
|
|
68
|
+
let highestApplied = 0;
|
|
69
|
+
for (const version of appliedVersions) {
|
|
70
|
+
if (version > highestApplied) highestApplied = version;
|
|
71
|
+
}
|
|
72
|
+
const pendingBelow = highestApplied >= through ? [] : sorted.filter((m) => m.baseline === void 0 && m.version <= through && !appliedVersions.has(m.version));
|
|
73
|
+
let highestReachable = highestApplied;
|
|
74
|
+
for (const migration of pendingBelow) {
|
|
75
|
+
if (migration.version > highestReachable) highestReachable = migration.version;
|
|
76
|
+
}
|
|
77
|
+
if (highestReachable < through) {
|
|
78
|
+
throw new MigrationError(
|
|
79
|
+
`Database history reaches version ${highestReachable} but baseline ${effectiveBaseline.version}_${effectiveBaseline.name} supersedes history through version ${through}; the migrations bridging the gap are missing from the input`,
|
|
80
|
+
effectiveBaseline.version,
|
|
81
|
+
"MIGRATION_BASELINE_GAP"
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
const pendingAbove = sorted.filter(
|
|
85
|
+
(m) => m.baseline === void 0 && m.version > through && !appliedVersions.has(m.version)
|
|
86
|
+
);
|
|
87
|
+
return [...pendingBelow, ...pendingAbove];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { SQLITE_USER_VERSION_MAX, applyBaselineOption, planPendingMigrations, resolveEffectiveBaseline };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ForbiddenSqlError } from './chunk-
|
|
1
|
+
import { ForbiddenSqlError } from './chunk-UC3SCMIN.mjs';
|
|
2
2
|
|
|
3
3
|
// src/core/internal-tables.ts
|
|
4
4
|
var INTERNAL_TABLE_PREFIX = "_sirannon_";
|
|
@@ -9,7 +9,10 @@ var PEER_STATE_TABLE = "_sirannon_peer_state";
|
|
|
9
9
|
var APPLIED_CHANGES_TABLE = "_sirannon_applied_changes";
|
|
10
10
|
var COLUMN_VERSIONS_TABLE = "_sirannon_column_versions";
|
|
11
11
|
var SYNC_STATE_TABLE = "_sirannon_sync_state";
|
|
12
|
+
var DEVICE_CURSORS_TABLE = "_sirannon_device_cursors";
|
|
13
|
+
var STAGED_CHANGES_TABLE = "_sirannon_staged_changes";
|
|
12
14
|
var CDC_TRIGGER_PREFIX = "_sirannon_trg_";
|
|
15
|
+
var LIVE_PROBE_TABLE_PREFIX = "_sirannon_live_probe_";
|
|
13
16
|
var SIRANNON_PREFIX = "_sirannon";
|
|
14
17
|
var SQLITE_PREFIX = "sqlite_";
|
|
15
18
|
var SIRANNON_MESSAGE = "Access to internal tables is not permitted: identifiers beginning with '_sirannon' are reserved";
|
|
@@ -265,4 +268,4 @@ function decodeHexBytes(hex) {
|
|
|
265
268
|
return bytes;
|
|
266
269
|
}
|
|
267
270
|
|
|
268
|
-
export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, INTERNAL_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, SAFE_INT_BOUND_TEXT, SYNC_STATE_TABLE, assertSqlAllowed, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, isReservedIdentifier };
|
|
271
|
+
export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX, LIVE_PROBE_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, SAFE_INT_BOUND_TEXT, STAGED_CHANGES_TABLE, SYNC_STATE_TABLE, assertSqlAllowed, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, isReservedIdentifier };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { SirannonError } from './chunk-
|
|
1
|
+
import { BackupManager, BackupScheduler } from './chunk-PIKHN33N.mjs';
|
|
2
|
+
import { WORKER_CANCELLED_CODE, deserializeError } from './chunk-4ISB7XMA.mjs';
|
|
3
|
+
import { SirannonError } from './chunk-UC3SCMIN.mjs';
|
|
4
4
|
import { Worker } from 'worker_threads';
|
|
5
5
|
import { existsSync } from 'fs';
|
|
6
6
|
import { resolve, dirname, join, sep } from 'path';
|
|
@@ -142,24 +142,65 @@ var WriterWorker = class _WriterWorker {
|
|
|
142
142
|
const entry = this.pending.get(res.id);
|
|
143
143
|
if (!entry) return;
|
|
144
144
|
this.pending.delete(res.id);
|
|
145
|
-
|
|
146
|
-
if (res.ok)
|
|
147
|
-
|
|
145
|
+
clearPendingTimers(entry);
|
|
146
|
+
if (res.ok) {
|
|
147
|
+
entry.resolve(res.value);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (res.error.code === WORKER_CANCELLED_CODE) {
|
|
151
|
+
entry.reject(
|
|
152
|
+
new SirannonError(
|
|
153
|
+
`The writer worker could not take this operation within ${this.timeoutMs}ms; it was not applied and is safe to retry`,
|
|
154
|
+
"WRITE_OVERLOADED"
|
|
155
|
+
)
|
|
156
|
+
);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
entry.reject(deserializeError(res.error));
|
|
148
160
|
}
|
|
149
161
|
rejectPending(id, err) {
|
|
150
162
|
const entry = this.pending.get(id);
|
|
151
163
|
if (!entry) return;
|
|
152
164
|
this.pending.delete(id);
|
|
153
|
-
|
|
165
|
+
clearPendingTimers(entry);
|
|
154
166
|
entry.reject(err);
|
|
155
167
|
}
|
|
168
|
+
unresponsiveError(waitedMs) {
|
|
169
|
+
return new SirannonError(
|
|
170
|
+
`Writer worker did not respond within ${waitedMs}ms; the operation's outcome is unknown`,
|
|
171
|
+
"WRITER_WORKER_TIMEOUT"
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
// On the deadline the host cancels the operation, which drops work the
|
|
175
|
+
// worker has not started, then allows one further timeout as a grace window.
|
|
176
|
+
// An operation still running when that window closes is rejected as
|
|
177
|
+
// indeterminate, because the write may or may not have reached the disk.
|
|
178
|
+
onDeadline(id) {
|
|
179
|
+
const entry = this.pending.get(id);
|
|
180
|
+
if (!entry) return;
|
|
181
|
+
const worker = this.worker;
|
|
182
|
+
if (!entry.cancellable || !worker) {
|
|
183
|
+
this.rejectPending(id, this.unresponsiveError(this.timeoutMs));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
worker.postMessage({ kind: "cancel", id });
|
|
188
|
+
} catch {
|
|
189
|
+
this.rejectPending(id, this.unresponsiveError(this.timeoutMs));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
entry.graceTimer = setTimeout(() => {
|
|
193
|
+
this.rejectPending(id, this.unresponsiveError(this.timeoutMs * 2));
|
|
194
|
+
}, this.timeoutMs);
|
|
195
|
+
entry.graceTimer.unref?.();
|
|
196
|
+
}
|
|
156
197
|
fault(errLike) {
|
|
157
198
|
if (this.closed || this.fatal) return;
|
|
158
199
|
const err = errLike instanceof Error ? errLike : new SirannonError(String(errLike), "WRITER_WORKER_ERROR");
|
|
159
200
|
const dead = this.worker;
|
|
160
201
|
this.worker = null;
|
|
161
202
|
for (const entry of this.pending.values()) {
|
|
162
|
-
|
|
203
|
+
clearPendingTimers(entry);
|
|
163
204
|
entry.reject(err);
|
|
164
205
|
}
|
|
165
206
|
this.pending.clear();
|
|
@@ -197,18 +238,11 @@ var WriterWorker = class _WriterWorker {
|
|
|
197
238
|
return new Promise((resolve2, reject) => {
|
|
198
239
|
let timer = null;
|
|
199
240
|
if (this.timeoutMs > 0) {
|
|
200
|
-
timer = setTimeout(() =>
|
|
201
|
-
this.rejectPending(
|
|
202
|
-
id,
|
|
203
|
-
new SirannonError(
|
|
204
|
-
`Writer worker did not respond within ${this.timeoutMs}ms; the operation's outcome is unknown`,
|
|
205
|
-
"WRITER_WORKER_TIMEOUT"
|
|
206
|
-
)
|
|
207
|
-
);
|
|
208
|
-
}, this.timeoutMs);
|
|
241
|
+
timer = setTimeout(() => this.onDeadline(id), this.timeoutMs);
|
|
209
242
|
timer.unref?.();
|
|
210
243
|
}
|
|
211
|
-
|
|
244
|
+
const cancellable = request.kind !== "open" && request.kind !== "close";
|
|
245
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, graceTimer: null, cancellable });
|
|
212
246
|
try {
|
|
213
247
|
worker.postMessage(message);
|
|
214
248
|
} catch (err) {
|
|
@@ -247,7 +281,8 @@ var WriterWorker = class _WriterWorker {
|
|
|
247
281
|
units: units.map((unit) => ({
|
|
248
282
|
statements: unit.statements.map((statement) => ({
|
|
249
283
|
sql: statement.sql,
|
|
250
|
-
params: statement.params ? [...statement.params] : []
|
|
284
|
+
params: statement.params ? [...statement.params] : [],
|
|
285
|
+
...statement.trusted === true ? { trusted: true } : {}
|
|
251
286
|
}))
|
|
252
287
|
}))
|
|
253
288
|
}),
|
|
@@ -289,12 +324,16 @@ var WriterWorker = class _WriterWorker {
|
|
|
289
324
|
}
|
|
290
325
|
this.worker = null;
|
|
291
326
|
for (const entry of this.pending.values()) {
|
|
292
|
-
|
|
327
|
+
clearPendingTimers(entry);
|
|
293
328
|
entry.reject(new SirannonError("Writer worker is closed", "WRITER_WORKER_CLOSED"));
|
|
294
329
|
}
|
|
295
330
|
this.pending.clear();
|
|
296
331
|
}
|
|
297
332
|
};
|
|
333
|
+
function clearPendingTimers(entry) {
|
|
334
|
+
if (entry.timer) clearTimeout(entry.timer);
|
|
335
|
+
if (entry.graceTimer) clearTimeout(entry.graceTimer);
|
|
336
|
+
}
|
|
298
337
|
function nodeWriterContext() {
|
|
299
338
|
const held = new AsyncLocalStorage();
|
|
300
339
|
return {
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// src/core/sync/sha256.ts
|
|
2
|
+
var K = new Uint32Array([
|
|
3
|
+
1116352408,
|
|
4
|
+
1899447441,
|
|
5
|
+
3049323471,
|
|
6
|
+
3921009573,
|
|
7
|
+
961987163,
|
|
8
|
+
1508970993,
|
|
9
|
+
2453635748,
|
|
10
|
+
2870763221,
|
|
11
|
+
3624381080,
|
|
12
|
+
310598401,
|
|
13
|
+
607225278,
|
|
14
|
+
1426881987,
|
|
15
|
+
1925078388,
|
|
16
|
+
2162078206,
|
|
17
|
+
2614888103,
|
|
18
|
+
3248222580,
|
|
19
|
+
3835390401,
|
|
20
|
+
4022224774,
|
|
21
|
+
264347078,
|
|
22
|
+
604807628,
|
|
23
|
+
770255983,
|
|
24
|
+
1249150122,
|
|
25
|
+
1555081692,
|
|
26
|
+
1996064986,
|
|
27
|
+
2554220882,
|
|
28
|
+
2821834349,
|
|
29
|
+
2952996808,
|
|
30
|
+
3210313671,
|
|
31
|
+
3336571891,
|
|
32
|
+
3584528711,
|
|
33
|
+
113926993,
|
|
34
|
+
338241895,
|
|
35
|
+
666307205,
|
|
36
|
+
773529912,
|
|
37
|
+
1294757372,
|
|
38
|
+
1396182291,
|
|
39
|
+
1695183700,
|
|
40
|
+
1986661051,
|
|
41
|
+
2177026350,
|
|
42
|
+
2456956037,
|
|
43
|
+
2730485921,
|
|
44
|
+
2820302411,
|
|
45
|
+
3259730800,
|
|
46
|
+
3345764771,
|
|
47
|
+
3516065817,
|
|
48
|
+
3600352804,
|
|
49
|
+
4094571909,
|
|
50
|
+
275423344,
|
|
51
|
+
430227734,
|
|
52
|
+
506948616,
|
|
53
|
+
659060556,
|
|
54
|
+
883997877,
|
|
55
|
+
958139571,
|
|
56
|
+
1322822218,
|
|
57
|
+
1537002063,
|
|
58
|
+
1747873779,
|
|
59
|
+
1955562222,
|
|
60
|
+
2024104815,
|
|
61
|
+
2227730452,
|
|
62
|
+
2361852424,
|
|
63
|
+
2428436474,
|
|
64
|
+
2756734187,
|
|
65
|
+
3204031479,
|
|
66
|
+
3329325298
|
|
67
|
+
]);
|
|
68
|
+
function rotr(x, n) {
|
|
69
|
+
return x >>> n | x << 32 - n;
|
|
70
|
+
}
|
|
71
|
+
function sha256Hex(input) {
|
|
72
|
+
const data = new TextEncoder().encode(input);
|
|
73
|
+
const bitLength = data.length * 8;
|
|
74
|
+
const paddedLength = (data.length + 8 >> 6) + 1 << 6;
|
|
75
|
+
const padded = new Uint8Array(paddedLength);
|
|
76
|
+
padded.set(data);
|
|
77
|
+
padded[data.length] = 128;
|
|
78
|
+
const view = new DataView(padded.buffer);
|
|
79
|
+
view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296), false);
|
|
80
|
+
view.setUint32(paddedLength - 4, bitLength >>> 0, false);
|
|
81
|
+
const state = new Uint32Array([
|
|
82
|
+
1779033703,
|
|
83
|
+
3144134277,
|
|
84
|
+
1013904242,
|
|
85
|
+
2773480762,
|
|
86
|
+
1359893119,
|
|
87
|
+
2600822924,
|
|
88
|
+
528734635,
|
|
89
|
+
1541459225
|
|
90
|
+
]);
|
|
91
|
+
const w = new Uint32Array(64);
|
|
92
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
93
|
+
for (let i = 0; i < 16; i++) {
|
|
94
|
+
w[i] = view.getUint32(offset + i * 4, false);
|
|
95
|
+
}
|
|
96
|
+
for (let i = 16; i < 64; i++) {
|
|
97
|
+
const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
|
|
98
|
+
const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
|
|
99
|
+
w[i] = w[i - 16] + s0 + w[i - 7] + s1 >>> 0;
|
|
100
|
+
}
|
|
101
|
+
let [a, b, c, d, e, f, g, h] = state;
|
|
102
|
+
for (let i = 0; i < 64; i++) {
|
|
103
|
+
const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
104
|
+
const ch = e & f ^ ~e & g;
|
|
105
|
+
const temp1 = h + s1 + ch + K[i] + w[i] >>> 0;
|
|
106
|
+
const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
107
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
108
|
+
const temp2 = s0 + maj >>> 0;
|
|
109
|
+
h = g;
|
|
110
|
+
g = f;
|
|
111
|
+
f = e;
|
|
112
|
+
e = d + temp1 >>> 0;
|
|
113
|
+
d = c;
|
|
114
|
+
c = b;
|
|
115
|
+
b = a;
|
|
116
|
+
a = temp1 + temp2 >>> 0;
|
|
117
|
+
}
|
|
118
|
+
state[0] = state[0] + a >>> 0;
|
|
119
|
+
state[1] = state[1] + b >>> 0;
|
|
120
|
+
state[2] = state[2] + c >>> 0;
|
|
121
|
+
state[3] = state[3] + d >>> 0;
|
|
122
|
+
state[4] = state[4] + e >>> 0;
|
|
123
|
+
state[5] = state[5] + f >>> 0;
|
|
124
|
+
state[6] = state[6] + g >>> 0;
|
|
125
|
+
state[7] = state[7] + h >>> 0;
|
|
126
|
+
}
|
|
127
|
+
return Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export { sha256Hex };
|