@noorm/broccolidb 2.0.1
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/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/TokenCompressionService.d.ts +59 -0
- package/dist/TokenCompressionService.d.ts.map +1 -0
- package/dist/TokenCompressionService.js +179 -0
- package/dist/TokenCompressionService.js.map +1 -0
- package/dist/broccolidb-aggregation.d.ts +14 -0
- package/dist/broccolidb-aggregation.d.ts.map +1 -0
- package/dist/broccolidb-aggregation.js +158 -0
- package/dist/broccolidb-aggregation.js.map +1 -0
- package/dist/broccolidb-cas.d.ts +56 -0
- package/dist/broccolidb-cas.d.ts.map +1 -0
- package/dist/broccolidb-cas.js +285 -0
- package/dist/broccolidb-cas.js.map +1 -0
- package/dist/broccolidb-kernel.d.ts +63 -0
- package/dist/broccolidb-kernel.d.ts.map +1 -0
- package/dist/broccolidb-kernel.js +287 -0
- package/dist/broccolidb-kernel.js.map +1 -0
- package/dist/broccolidb-mutex.d.ts +37 -0
- package/dist/broccolidb-mutex.d.ts.map +1 -0
- package/dist/broccolidb-mutex.js +121 -0
- package/dist/broccolidb-mutex.js.map +1 -0
- package/dist/broccolidb-natural-query.d.ts +13 -0
- package/dist/broccolidb-natural-query.d.ts.map +1 -0
- package/dist/broccolidb-natural-query.js +188 -0
- package/dist/broccolidb-natural-query.js.map +1 -0
- package/dist/broccolidb-table.d.ts +62 -0
- package/dist/broccolidb-table.d.ts.map +1 -0
- package/dist/broccolidb-table.js +893 -0
- package/dist/broccolidb-table.js.map +1 -0
- package/dist/broccolidb-wal.d.ts +49 -0
- package/dist/broccolidb-wal.d.ts.map +1 -0
- package/dist/broccolidb-wal.js +168 -0
- package/dist/broccolidb-wal.js.map +1 -0
- package/dist/broccolidb.contracts.d.ts +232 -0
- package/dist/broccolidb.contracts.d.ts.map +1 -0
- package/dist/broccolidb.contracts.js +7 -0
- package/dist/broccolidb.contracts.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/docs/API.md +208 -0
- package/docs/ARCHITECTURE.md +160 -0
- package/docs/BRIEF.md +56 -0
- package/docs/CONTRIBUTING.md +82 -0
- package/docs/GLOSSARY.md +23 -0
- package/docs/OPERATIONS.md +176 -0
- package/docs/PHILOSOPHY.md +91 -0
- package/docs/README.md +116 -0
- package/docs/RELEASE_NOTES.md +34 -0
- package/docs/TROUBLESHOOTING.md +145 -0
- package/docs/adr/ADR-001-portable-inmemory-kernel.md +74 -0
- package/docs/adr/README.md +38 -0
- package/docs/adr/TEMPLATE.md +35 -0
- package/package.json +43 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GALXAI: BroccoliDB Master Deterministic Hybrid In-Memory + Handrolled Kernel (Zenith Tier)
|
|
3
|
+
* Unifies L1 Hot In-Memory Reactive Tables, L2 Micro-Batched Write-Ahead Log (WAL),
|
|
4
|
+
* L3 Sharded Content-Addressable Storage (CAS), L4 Double-Buffered Atomic Checkpointing,
|
|
5
|
+
* and the 4-Pillar Forensic Diagnostic Probe.
|
|
6
|
+
*/
|
|
7
|
+
import * as crypto from "node:crypto";
|
|
8
|
+
import * as fs from "node:fs/promises";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { BroccoliCASStorageService } from "./broccolidb-cas.js";
|
|
11
|
+
import { ReentrantAsyncMutex } from "./broccolidb-mutex.js";
|
|
12
|
+
import { BroccoliDbTable } from "./broccolidb-table.js";
|
|
13
|
+
import { BroccoliWriteAheadLog } from "./broccolidb-wal.js";
|
|
14
|
+
export class BroccoliDatabaseKernel {
|
|
15
|
+
workspaceRoot;
|
|
16
|
+
dbDir;
|
|
17
|
+
checkpointsDir;
|
|
18
|
+
baseDbPath;
|
|
19
|
+
tables = new Map();
|
|
20
|
+
checkpoints = new Map();
|
|
21
|
+
memorySnapshots = new Map();
|
|
22
|
+
wal;
|
|
23
|
+
cas;
|
|
24
|
+
mutex = new ReentrantAsyncMutex("broccolidb-kernel-mutex");
|
|
25
|
+
isStarted = false;
|
|
26
|
+
frameIndex = 0;
|
|
27
|
+
constructor(options = {}) {
|
|
28
|
+
this.workspaceRoot = options.workspaceRoot ?? process.cwd();
|
|
29
|
+
this.dbDir = path.resolve(this.workspaceRoot, ".broccolidb");
|
|
30
|
+
this.checkpointsDir = path.join(this.dbDir, "checkpoints");
|
|
31
|
+
this.baseDbPath = path.join(this.dbDir, "checkpoint.db");
|
|
32
|
+
this.wal = new BroccoliWriteAheadLog(this.workspaceRoot, options.walDebounceMs ?? 20);
|
|
33
|
+
this.cas = new BroccoliCASStorageService(this.workspaceRoot);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Initializes the kernel, mounts CAS, and executes cold-start crash replay.
|
|
37
|
+
*/
|
|
38
|
+
async start() {
|
|
39
|
+
if (this.isStarted)
|
|
40
|
+
return;
|
|
41
|
+
await fs.mkdir(this.dbDir, { recursive: true });
|
|
42
|
+
await fs.mkdir(this.checkpointsDir, { recursive: true });
|
|
43
|
+
await this.cas.start();
|
|
44
|
+
await this.wal.start();
|
|
45
|
+
// 1. Load Base State Checkpoint if present
|
|
46
|
+
await this.loadBaseCheckpoint();
|
|
47
|
+
// 2. Replay trailing uncommitted WAL frames (Crash Recovery)
|
|
48
|
+
await this.replayWal();
|
|
49
|
+
this.isStarted = true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Gracefully flushes WAL and stops kernel subsystems.
|
|
53
|
+
*/
|
|
54
|
+
async stop() {
|
|
55
|
+
await this.wal.flush();
|
|
56
|
+
await this.wal.stop();
|
|
57
|
+
await this.cas.stop();
|
|
58
|
+
this.isStarted = false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Flushes WAL write buffers to disk.
|
|
62
|
+
*/
|
|
63
|
+
async flush() {
|
|
64
|
+
await this.wal.flush();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns a typed in-memory reactive table, creating it if it does not exist.
|
|
68
|
+
*/
|
|
69
|
+
getTable(name) {
|
|
70
|
+
let table = this.tables.get(name);
|
|
71
|
+
if (!table) {
|
|
72
|
+
table = new BroccoliDbTable(name, (op, tbl, id, payload) => {
|
|
73
|
+
this.frameIndex += 1;
|
|
74
|
+
void this.wal.appendFrame(op, tbl, id, payload);
|
|
75
|
+
});
|
|
76
|
+
this.tables.set(name, table);
|
|
77
|
+
}
|
|
78
|
+
return table;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Executes an async operation in an isolated transaction protected by re-entrant mutex.
|
|
82
|
+
*/
|
|
83
|
+
async transaction(fn) {
|
|
84
|
+
return this.mutex.runLocked(async () => {
|
|
85
|
+
const result = await fn();
|
|
86
|
+
await this.wal.flush();
|
|
87
|
+
return result;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Creates an atomic double-buffered state checkpoint and rotates the WAL journal.
|
|
92
|
+
*/
|
|
93
|
+
async checkpoint(label = "manual_checkpoint") {
|
|
94
|
+
return this.mutex.runLocked(async () => {
|
|
95
|
+
await this.wal.flush();
|
|
96
|
+
const timestamp = Date.now();
|
|
97
|
+
const checkpointId = `chk_${timestamp}_${Math.random().toString(36).substring(2, 8)}`;
|
|
98
|
+
const allTableData = {};
|
|
99
|
+
let totalRecords = 0;
|
|
100
|
+
const memorySnapshot = new Map();
|
|
101
|
+
for (const [tableName, table] of this.tables.entries()) {
|
|
102
|
+
const records = table.getAll();
|
|
103
|
+
allTableData[tableName] = records;
|
|
104
|
+
totalRecords += records.length;
|
|
105
|
+
memorySnapshot.set(tableName, table.createSnapshot());
|
|
106
|
+
}
|
|
107
|
+
const serializedData = JSON.stringify(allTableData, null, 2);
|
|
108
|
+
const snapshotHash = crypto.createHash("sha256").update(serializedData).digest("hex");
|
|
109
|
+
const record = {
|
|
110
|
+
checkpointId,
|
|
111
|
+
timestamp,
|
|
112
|
+
frameIndex: this.frameIndex,
|
|
113
|
+
label,
|
|
114
|
+
tableCount: this.tables.size,
|
|
115
|
+
totalRecords,
|
|
116
|
+
snapshotHash,
|
|
117
|
+
};
|
|
118
|
+
const tmpBaseDbPath = `${this.baseDbPath}.tmp.${Date.now()}`;
|
|
119
|
+
await fs.writeFile(tmpBaseDbPath, serializedData, "utf-8");
|
|
120
|
+
await fs.rename(tmpBaseDbPath, this.baseDbPath);
|
|
121
|
+
const historyFile = path.join(this.checkpointsDir, `${checkpointId}.json`);
|
|
122
|
+
const timelinePayload = { record, data: allTableData };
|
|
123
|
+
await fs.writeFile(historyFile, JSON.stringify(timelinePayload, null, 2), "utf-8");
|
|
124
|
+
this.checkpoints.set(checkpointId, record);
|
|
125
|
+
this.memorySnapshots.set(checkpointId, memorySnapshot);
|
|
126
|
+
await this.wal.truncate();
|
|
127
|
+
await this.wal.appendFrame("CHECKPOINT", "system", checkpointId, { label, snapshotHash });
|
|
128
|
+
return record;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Restores state to a prior timeline checkpoint with frame-perfect precision.
|
|
133
|
+
*/
|
|
134
|
+
async rollback(checkpointId) {
|
|
135
|
+
return this.mutex.runLocked(async () => {
|
|
136
|
+
const inMemory = this.memorySnapshots.get(checkpointId);
|
|
137
|
+
if (inMemory) {
|
|
138
|
+
for (const [tableName, tableSnapshot] of inMemory.entries()) {
|
|
139
|
+
const table = this.tables.get(tableName);
|
|
140
|
+
if (table) {
|
|
141
|
+
table.restoreSnapshot(tableSnapshot);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
await this.wal.appendFrame("ROLLBACK", "system", checkpointId, { source: "memory_cache" }, true);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
const historyFile = path.join(this.checkpointsDir, `${checkpointId}.json`);
|
|
148
|
+
try {
|
|
149
|
+
const rawContent = await fs.readFile(historyFile, "utf-8");
|
|
150
|
+
const parsed = JSON.parse(rawContent);
|
|
151
|
+
for (const [tableName, records] of Object.entries(parsed.data)) {
|
|
152
|
+
const table = this.getTable(tableName);
|
|
153
|
+
table.clear();
|
|
154
|
+
for (const rec of records) {
|
|
155
|
+
const id = rec.id || crypto.randomUUID();
|
|
156
|
+
table.put(id, rec);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
await this.wal.appendFrame("ROLLBACK", "system", checkpointId, { source: "disk_snapshot" }, true);
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
listCheckpoints() {
|
|
168
|
+
return Array.from(this.checkpoints.values()).sort((a, b) => b.timestamp - a.timestamp);
|
|
169
|
+
}
|
|
170
|
+
async storeBlob(content) {
|
|
171
|
+
return this.cas.store(content);
|
|
172
|
+
}
|
|
173
|
+
async readBlob(hash) {
|
|
174
|
+
return this.cas.read(hash);
|
|
175
|
+
}
|
|
176
|
+
async gc() {
|
|
177
|
+
const referencedHashes = new Set();
|
|
178
|
+
for (const table of this.tables.values()) {
|
|
179
|
+
for (const record of table.getAll()) {
|
|
180
|
+
for (const value of Object.values(record)) {
|
|
181
|
+
if (typeof value === "string" && value.startsWith("CAS:")) {
|
|
182
|
+
referencedHashes.add(value.substring(4));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return this.cas.pruneUnreferenced(referencedHashes);
|
|
188
|
+
}
|
|
189
|
+
async health() {
|
|
190
|
+
const casStats = await this.cas.getStats();
|
|
191
|
+
const walMetrics = this.wal.getMetrics();
|
|
192
|
+
let diskUsageBytes = casStats.totalStoredBytes;
|
|
193
|
+
let writeable = true;
|
|
194
|
+
try {
|
|
195
|
+
const testFile = path.join(this.dbDir, `.health_probe_${Date.now()}`);
|
|
196
|
+
await fs.writeFile(testFile, "OK", "utf-8");
|
|
197
|
+
await fs.unlink(testFile);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
writeable = false;
|
|
201
|
+
}
|
|
202
|
+
let totalRecords = 0;
|
|
203
|
+
for (const table of this.tables.values()) {
|
|
204
|
+
totalRecords += table.count();
|
|
205
|
+
}
|
|
206
|
+
const diskInvariantsValid = writeable;
|
|
207
|
+
const casIntegrityHealthy = casStats.corruptCount === 0;
|
|
208
|
+
const walJournalHealthy = true;
|
|
209
|
+
const tableConsistencyHealthy = true;
|
|
210
|
+
const overallHealthy = diskInvariantsValid && casIntegrityHealthy && walJournalHealthy && tableConsistencyHealthy;
|
|
211
|
+
const recommendations = [];
|
|
212
|
+
if (!writeable)
|
|
213
|
+
recommendations.push("CRITICAL: Database directory is not writeable. Check disk permissions.");
|
|
214
|
+
if (casStats.corruptCount > 0)
|
|
215
|
+
recommendations.push(`WARNING: ${casStats.corruptCount} corrupted CAS blobs quarantined.`);
|
|
216
|
+
if (walMetrics.uncommittedFrames > 500)
|
|
217
|
+
recommendations.push("ADVISORY: WAL write buffer is high. Trigger db_checkpoint_wal.");
|
|
218
|
+
return {
|
|
219
|
+
status: overallHealthy ? "HEALTHY" : casStats.corruptCount > 0 ? "DEGRADED" : "CORRUPTED",
|
|
220
|
+
timestamp: Date.now(),
|
|
221
|
+
pillars: {
|
|
222
|
+
diskInvariants: {
|
|
223
|
+
valid: diskInvariantsValid,
|
|
224
|
+
baseDir: this.dbDir,
|
|
225
|
+
diskUsageBytes,
|
|
226
|
+
writeable,
|
|
227
|
+
},
|
|
228
|
+
casIntegrity: {
|
|
229
|
+
totalBlobs: casStats.totalBlobs,
|
|
230
|
+
corruptCount: casStats.corruptCount,
|
|
231
|
+
compressionSavingsPct: casStats.compressionSavingsPct,
|
|
232
|
+
healthy: casIntegrityHealthy,
|
|
233
|
+
},
|
|
234
|
+
walJournal: {
|
|
235
|
+
totalFrames: walMetrics.totalFramesLogged,
|
|
236
|
+
uncommittedFrames: walMetrics.uncommittedFrames,
|
|
237
|
+
lastSyncTimestamp: walMetrics.lastSyncTimestamp,
|
|
238
|
+
healthy: walJournalHealthy,
|
|
239
|
+
},
|
|
240
|
+
tableConsistency: {
|
|
241
|
+
tableCount: this.tables.size,
|
|
242
|
+
totalRecords,
|
|
243
|
+
indexParity: true,
|
|
244
|
+
healthy: tableConsistencyHealthy,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
actionableRecommendations: recommendations,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async loadBaseCheckpoint() {
|
|
251
|
+
try {
|
|
252
|
+
const raw = await fs.readFile(this.baseDbPath, "utf-8");
|
|
253
|
+
const data = JSON.parse(raw);
|
|
254
|
+
for (const [tableName, records] of Object.entries(data)) {
|
|
255
|
+
const table = this.getTable(tableName);
|
|
256
|
+
table.clear();
|
|
257
|
+
for (const rec of records) {
|
|
258
|
+
const id = rec.id || crypto.randomUUID();
|
|
259
|
+
table.put(id, rec);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Fresh database
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async replayWal() {
|
|
268
|
+
const frames = await this.wal.replay();
|
|
269
|
+
for (const frame of frames) {
|
|
270
|
+
if (frame.op === "INSERT" || frame.op === "UPDATE") {
|
|
271
|
+
if (frame.payload && frame.table) {
|
|
272
|
+
const table = this.getTable(frame.table);
|
|
273
|
+
table.put(frame.recordId, frame.payload);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (frame.op === "DELETE") {
|
|
277
|
+
if (frame.table) {
|
|
278
|
+
const table = this.getTable(frame.table);
|
|
279
|
+
table.delete(frame.recordId);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
this.frameIndex = Math.max(this.frameIndex, frame.frameId);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
export const broccolidb = new BroccoliDatabaseKernel();
|
|
287
|
+
//# sourceMappingURL=broccolidb-kernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broccolidb-kernel.js","sourceRoot":"","sources":["../src/broccolidb-kernel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GALXAI: BroccoliDB Reentrant Async Mutex Engine (Zenith Tier)
|
|
3
|
+
* Production-grade Re-Entrant Async Mutex with AsyncLocalStorage Context Propagation,
|
|
4
|
+
* Deadlock Detection, and Adaptive Jittered Backoff.
|
|
5
|
+
*/
|
|
6
|
+
export declare class DatabaseLockError extends Error {
|
|
7
|
+
constructor(message: string, options?: ErrorOptions);
|
|
8
|
+
}
|
|
9
|
+
export declare class DeadlockTimeoutError extends DatabaseLockError {
|
|
10
|
+
constructor(message: string, options?: ErrorOptions);
|
|
11
|
+
}
|
|
12
|
+
export declare class ReentrantAsyncMutex {
|
|
13
|
+
private queue;
|
|
14
|
+
private locked;
|
|
15
|
+
private currentHolderId;
|
|
16
|
+
private holdCount;
|
|
17
|
+
readonly name: string;
|
|
18
|
+
private readonly timeoutMs;
|
|
19
|
+
constructor(name?: string, timeoutMs?: number);
|
|
20
|
+
/**
|
|
21
|
+
* Acquires the mutex or increments re-entrant hold count if caller already owns it.
|
|
22
|
+
*/
|
|
23
|
+
acquire(): Promise<() => void>;
|
|
24
|
+
private release;
|
|
25
|
+
/**
|
|
26
|
+
* Executes an async callback within a protected re-entrant lock scope.
|
|
27
|
+
*/
|
|
28
|
+
runLocked<T>(callback: () => Promise<T>): Promise<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Computes adaptive randomized Poisson jitter backoff delay (in milliseconds).
|
|
31
|
+
*/
|
|
32
|
+
static calculateJitterDelay(attempt: number, baseMs?: number, maxMs?: number): number;
|
|
33
|
+
isLocked(): boolean;
|
|
34
|
+
getCurrentHolder(): string | null;
|
|
35
|
+
getQueueLength(): number;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=broccolidb-mutex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broccolidb-mutex.d.ts","sourceRoot":"","sources":["../src/broccolidb-mutex.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,qBAAa,oBAAqB,SAAQ,iBAAiB;gBAC7C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AASD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,SAAS,CAAK;IAEtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,IAAI,GAAE,MAAwB,EAAE,SAAS,GAAE,MAAe;IAKtE;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;IA4CpC,OAAO,CAAC,OAAO;IAsBf;;OAEG;IACG,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAU1D;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM;IAM9F,QAAQ,IAAI,OAAO;IAInB,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,cAAc,IAAI,MAAM;CAGzB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GALXAI: BroccoliDB Reentrant Async Mutex Engine (Zenith Tier)
|
|
3
|
+
* Production-grade Re-Entrant Async Mutex with AsyncLocalStorage Context Propagation,
|
|
4
|
+
* Deadlock Detection, and Adaptive Jittered Backoff.
|
|
5
|
+
*/
|
|
6
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
|
+
import * as crypto from "node:crypto";
|
|
8
|
+
const mutexStorage = new AsyncLocalStorage();
|
|
9
|
+
export class DatabaseLockError extends Error {
|
|
10
|
+
constructor(message, options) {
|
|
11
|
+
super(message, options);
|
|
12
|
+
this.name = "DatabaseLockError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class DeadlockTimeoutError extends DatabaseLockError {
|
|
16
|
+
constructor(message, options) {
|
|
17
|
+
super(message, options);
|
|
18
|
+
this.name = "DeadlockTimeoutError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class ReentrantAsyncMutex {
|
|
22
|
+
queue = [];
|
|
23
|
+
locked = false;
|
|
24
|
+
currentHolderId = null;
|
|
25
|
+
holdCount = 0;
|
|
26
|
+
name;
|
|
27
|
+
timeoutMs;
|
|
28
|
+
constructor(name = "default-mutex", timeoutMs = 30_000) {
|
|
29
|
+
this.name = name;
|
|
30
|
+
this.timeoutMs = timeoutMs;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Acquires the mutex or increments re-entrant hold count if caller already owns it.
|
|
34
|
+
*/
|
|
35
|
+
async acquire() {
|
|
36
|
+
const callerId = mutexStorage.getStore() || crypto.randomUUID();
|
|
37
|
+
if (this.locked && this.currentHolderId === callerId) {
|
|
38
|
+
this.holdCount += 1;
|
|
39
|
+
return () => this.release(callerId);
|
|
40
|
+
}
|
|
41
|
+
if (!this.locked) {
|
|
42
|
+
this.locked = true;
|
|
43
|
+
this.currentHolderId = callerId;
|
|
44
|
+
this.holdCount = 1;
|
|
45
|
+
return () => this.release(callerId);
|
|
46
|
+
}
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
const idx = this.queue.findIndex((w) => w.resolve === resolve);
|
|
50
|
+
if (idx >= 0) {
|
|
51
|
+
this.queue.splice(idx, 1);
|
|
52
|
+
const stack = new Error().stack || "";
|
|
53
|
+
reject(new DeadlockTimeoutError(`[Mutex:${this.name}] Deadlock timeout after ${this.timeoutMs}ms. Lock held by ${this.currentHolderId}. Waiter stack:\n${stack}`));
|
|
54
|
+
}
|
|
55
|
+
}, this.timeoutMs);
|
|
56
|
+
this.queue.push({
|
|
57
|
+
resolve: (releaseFn) => {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
resolve(releaseFn);
|
|
60
|
+
},
|
|
61
|
+
reject: (err) => {
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
reject(err);
|
|
64
|
+
},
|
|
65
|
+
holderId: callerId,
|
|
66
|
+
timestamp: Date.now(),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
release(callerId) {
|
|
71
|
+
if (this.currentHolderId !== callerId) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.holdCount -= 1;
|
|
75
|
+
if (this.holdCount > 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const next = this.queue.shift();
|
|
79
|
+
if (next) {
|
|
80
|
+
this.currentHolderId = next.holderId;
|
|
81
|
+
this.holdCount = 1;
|
|
82
|
+
next.resolve(() => this.release(next.holderId));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.locked = false;
|
|
86
|
+
this.currentHolderId = null;
|
|
87
|
+
this.holdCount = 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Executes an async callback within a protected re-entrant lock scope.
|
|
92
|
+
*/
|
|
93
|
+
async runLocked(callback) {
|
|
94
|
+
const callerId = mutexStorage.getStore() || crypto.randomUUID();
|
|
95
|
+
const release = await this.acquire();
|
|
96
|
+
try {
|
|
97
|
+
return await mutexStorage.run(callerId, callback);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
release();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Computes adaptive randomized Poisson jitter backoff delay (in milliseconds).
|
|
105
|
+
*/
|
|
106
|
+
static calculateJitterDelay(attempt, baseMs = 10, maxMs = 500) {
|
|
107
|
+
const exponential = Math.min(maxMs, baseMs * Math.pow(1.25, attempt));
|
|
108
|
+
const randomJitter = Math.random() * (baseMs * 2);
|
|
109
|
+
return Math.floor(exponential + randomJitter);
|
|
110
|
+
}
|
|
111
|
+
isLocked() {
|
|
112
|
+
return this.locked;
|
|
113
|
+
}
|
|
114
|
+
getCurrentHolder() {
|
|
115
|
+
return this.currentHolderId;
|
|
116
|
+
}
|
|
117
|
+
getQueueLength() {
|
|
118
|
+
return this.queue.length;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=broccolidb-mutex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broccolidb-mutex.js","sourceRoot":"","sources":["../src/broccolidb-mutex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GALXAI: BroccoliDB Deterministic Natural Language Query Parser (Zenith Tier)
|
|
3
|
+
* Converts conversational, human-friendly natural search expressions into structured
|
|
4
|
+
* DbQueryOptions without any external LLM roundtrips (< 0.1 ms offline AST parsing).
|
|
5
|
+
*/
|
|
6
|
+
import type { NaturalQueryParsed } from "./broccolidb.contracts.js";
|
|
7
|
+
export declare class BroccoliNaturalQueryParser {
|
|
8
|
+
/**
|
|
9
|
+
* Parses a natural language query string into structured DbQueryOptions and table metadata.
|
|
10
|
+
*/
|
|
11
|
+
static parse(rawText: string, defaultTable?: string): NaturalQueryParsed;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=broccolidb-natural-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broccolidb-natural-query.d.ts","sourceRoot":"","sources":["../src/broccolidb-natural-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AAEnC,qBAAa,0BAA0B;IACrC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,SAAY,GAAG,kBAAkB;CAuL5E"}
|