@cortexkit/opencode-magic-context 0.49.4 → 0.49.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-search-worker.js +5 -5
- package/dist/{compaction-marker-candidates-dd638ypn.js → compaction-marker-candidates-cz72pm1t.js} +2 -2
- package/dist/compaction-marker-candidates-worker.js +2 -2
- package/dist/{conflict-warning-hook-ae8nmv7c.js → conflict-warning-hook-1jq1rxx7.js} +5 -5
- package/dist/{context-yg023c5r.js → context-ae3gxdye.js} +23 -23
- package/dist/{embedding-backfill-aj488s8x.js → embedding-backfill-dtjmyktb.js} +6 -6
- package/dist/{index-kb9nn0a0.js → index-0nnd4bry.js} +2 -2
- package/dist/{index-yqps2zsv.js → index-1j8jcjpa.js} +1 -1
- package/dist/{index-3wckxwfp.js → index-1xaw2pq8.js} +5 -5
- package/dist/{index-m4p77myp.js → index-6q5h70h2.js} +1 -1
- package/dist/{index-7ndnvw7a.js → index-7q1m1qjk.js} +1 -1
- package/dist/{index-6m7rdv7y.js → index-9m7bn21d.js} +1 -1
- package/dist/{index-c0b01zrc.js → index-9s58tq95.js} +3 -3
- package/dist/{index-p2hs3rps.js → index-a796ct3s.js} +4 -4
- package/dist/{index-qvr78ej6.js → index-ab3bgm2m.js} +2 -2
- package/dist/{index-znzgze2v.js → index-besxhcsh.js} +7 -7
- package/dist/{index-7w18gg78.js → index-bg5qqene.js} +1 -1
- package/dist/{index-fst3t0d9.js → index-ch08qwgd.js} +8 -8
- package/dist/{index-dd18gej8.js → index-ck6y3td2.js} +3 -3
- package/dist/{index-7jzrrxap.js → index-cm4hmxyk.js} +1 -1
- package/dist/{index-yxawqmdd.js → index-f3dnvnw6.js} +1 -1
- package/dist/{index-41gqa557.js → index-g9exahnx.js} +1 -1
- package/dist/{index-bhk710rw.js → index-hr64sth2.js} +1 -1
- package/dist/{index-gcdb3rqw.js → index-j55vn694.js} +1 -1
- package/dist/{index-x3y1np1h.js → index-mj1fgfrk.js} +23 -23
- package/dist/{index-fjtgekd4.js → index-s0gsmthp.js} +4 -4
- package/dist/{index-v4bqjy56.js → index-vh3e2mvr.js} +17 -17
- package/dist/{index-jpm52v9x.js → index-vnjhmkwk.js} +1 -1
- package/dist/{index-7zg9dvx0.js → index-vztbgcdk.js} +4 -4
- package/dist/{index-xfbfrngb.js → index-xqyj5c85.js} +2 -2
- package/dist/{index-2mqps3c1.js → index-zgzdm6dg.js} +9 -9
- package/dist/index.js +34 -34
- package/dist/{message-index-bounded-pv6ct15d.js → message-index-bounded-630j53ps.js} +9 -9
- package/dist/{message-index-jqa7qd0s.js → message-index-c84wm2g0.js} +9 -9
- package/dist/{message-time-backfill-8x06r9kx.js → message-time-backfill-8kj57qe3.js} +1 -1
- package/dist/migration-worker.js +6 -6
- package/dist/{project-embedding-registry-fcmszatg.js → project-embedding-registry-vv59t7ah.js} +5 -5
- package/dist/raw-ordinal-warmup-worker.js +6 -6
- package/dist/{read-session-chunk-cwgjwjd0.js → read-session-chunk-t3vjd0h0.js} +5 -5
- package/dist/{read-session-raw-z38cn0as.js → read-session-raw-gf7eytnm.js} +2 -2
- package/dist/{recomp-orchestrator-xw9wt5bm.js → recomp-orchestrator-1d08g57a.js} +20 -20
- package/dist/{search-v1t47s2q.js → search-kth2p6cc.js} +16 -16
- package/dist/{send-session-notification-yp9m5g4p.js → send-session-notification-3j6krd4w.js} +4 -4
- package/dist/{sqlite-mhjkerzq.js → sqlite-d7edbk1s.js} +1 -1
- package/dist/{storage-memory-07fx57k6.js → storage-memory-af5zdz98.js} +2 -2
- package/dist/{storage-tags-0ssbmzg9.js → storage-tags-dyj7mmbq.js} +2 -2
- package/dist/{transform-postprocess-phase-ttra554y.js → transform-postprocess-phase-bv3kb5s1.js} +20 -20
- package/dist/v2/auto-search-worker.js +5 -5
- package/dist/v2/{compaction-marker-candidates-1s21e2fz.js → compaction-marker-candidates-6gqp5wrc.js} +2 -2
- package/dist/v2/compaction-marker-candidates-worker.js +2 -2
- package/dist/v2/{context-6en6a8ar.js → context-p8f2shp1.js} +23 -23
- package/dist/v2/{embedding-backfill-9hbkfvnz.js → embedding-backfill-cg4rv90f.js} +6 -6
- package/dist/v2/{message-index-h8ssgq3q.js → message-index-3ws17x1g.js} +9 -9
- package/dist/v2/{message-index-bounded-c0810p5w.js → message-index-bounded-yzxmf6vp.js} +9 -9
- package/dist/v2/{message-time-backfill-cje68egj.js → message-time-backfill-5nf10c65.js} +1 -1
- package/dist/v2/migration-worker.js +6 -6
- package/dist/v2/{project-embedding-registry-42th7k1z.js → project-embedding-registry-rsnf2263.js} +5 -5
- package/dist/v2/raw-ordinal-warmup-worker.js +6 -6
- package/dist/v2/{read-session-chunk-n86v9xfg.js → read-session-chunk-vtb0w2kd.js} +5 -5
- package/dist/v2/{read-session-raw-3b3ehga4.js → read-session-raw-gpcddemt.js} +2 -2
- package/dist/v2/{recomp-orchestrator-krvsbnds.js → recomp-orchestrator-v64r4s4r.js} +19 -19
- package/dist/v2/{search-048v8y02.js → search-bpa4fxq1.js} +16 -16
- package/dist/v2/{send-session-notification-a4h2azxa.js → send-session-notification-5aj2j7vf.js} +4 -4
- package/dist/v2/{server-9a6v0wth.js → server-09g9pkvx.js} +7 -7
- package/dist/v2/{server-kb9nn0a0.js → server-0nnd4bry.js} +2 -2
- package/dist/v2/{server-cjz51jm2.js → server-158ehmk2.js} +3 -3
- package/dist/v2/{server-3dqjhchy.js → server-387vkhjq.js} +1 -1
- package/dist/v2/{server-czb2rkpk.js → server-4tn95znb.js} +1 -1
- package/dist/v2/{server-9290a1mb.js → server-6a9mxnb2.js} +1 -1
- package/dist/v2/{server-e2v4m8xe.js → server-7skbfb81.js} +17 -17
- package/dist/v2/{server-4enr7s6x.js → server-9zqewm6g.js} +1 -1
- package/dist/v2/{server-hetyb88z.js → server-aa9w15cs.js} +8 -8
- package/dist/v2/{server-q6j5dasr.js → server-btgnsv7w.js} +1 -1
- package/dist/v2/{server-7jzrrxap.js → server-cm4hmxyk.js} +1 -1
- package/dist/v2/{server-5zrpr764.js → server-f9py7s7a.js} +1 -1
- package/dist/v2/{server-4n2tknpc.js → server-fby0cxbq.js} +4 -4
- package/dist/v2/{server-8wcf79fe.js → server-keswwkvv.js} +1 -1
- package/dist/v2/{server-3bc6k4k4.js → server-qn23p4h7.js} +5 -5
- package/dist/v2/{server-cvgn49tr.js → server-wrem2nmz.js} +1 -1
- package/dist/v2/{server-8pqnnmf9.js → server-ww9nr8pe.js} +2 -2
- package/dist/v2/{server-rygvffsf.js → server-x2r63c0x.js} +4 -4
- package/dist/v2/{server-pcygfdbs.js → server-yd01snxq.js} +1 -1
- package/dist/v2/{server-2htmbqbv.js → server-yezz0cp2.js} +1 -1
- package/dist/v2/server.js +2 -2
- package/dist/v2/{sqlite-mhjkerzq.js → sqlite-d7edbk1s.js} +1 -1
- package/dist/v2/{storage-memory-07fx57k6.js → storage-memory-af5zdz98.js} +2 -2
- package/dist/v2/{storage-tags-3a4cavqb.js → storage-tags-d47bpaqa.js} +2 -2
- package/dist/v2/{wrapup-orchestrator-r2v7kgy3.js → wrapup-orchestrator-cahk37n7.js} +19 -19
- package/dist/{wrapup-orchestrator-z7agncp8.js → wrapup-orchestrator-mqp0v195.js} +21 -21
- package/package.json +1 -1
- package/src/shared/sqlite-acquisition-routing.test.ts +4 -3
- package/src/shared/sqlite-foreground-wait.test.ts +140 -0
- package/src/shared/sqlite-pass-scope.test.ts +4 -4
- package/src/shared/sqlite.ts +2 -2
|
@@ -2,7 +2,7 @@ import"./server-pavzsdc6.js";
|
|
|
2
2
|
import {
|
|
3
3
|
sessionLog2
|
|
4
4
|
} from "./server-t4k4qexw.js";
|
|
5
|
-
import"./server-
|
|
5
|
+
import"./server-wrem2nmz.js";
|
|
6
6
|
import {
|
|
7
7
|
COMPARTMENT_LEASE_RENEWAL_MS,
|
|
8
8
|
acquireCompartmentLease,
|
|
@@ -19,13 +19,13 @@ import {
|
|
|
19
19
|
registerActiveCompartmentRun,
|
|
20
20
|
setRecompStarting2,
|
|
21
21
|
setRecompTerminal2
|
|
22
|
-
} from "./server-
|
|
22
|
+
} from "./server-7skbfb81.js";
|
|
23
23
|
import"./server-kzns2hbz.js";
|
|
24
24
|
import"./server-hb6xhh9q.js";
|
|
25
|
-
import"./server-
|
|
26
|
-
import"./server-
|
|
27
|
-
import"./server-
|
|
28
|
-
import"./server-
|
|
25
|
+
import"./server-0nnd4bry.js";
|
|
26
|
+
import"./server-yezz0cp2.js";
|
|
27
|
+
import"./server-keswwkvv.js";
|
|
28
|
+
import"./server-qn23p4h7.js";
|
|
29
29
|
import {
|
|
30
30
|
getWrapupInProgressState,
|
|
31
31
|
acquireWrapupInProgress,
|
|
@@ -34,39 +34,39 @@ import {
|
|
|
34
34
|
getHistorianFailureState,
|
|
35
35
|
clearEmergencyRecovery,
|
|
36
36
|
prepareRawSessionOrdinals2
|
|
37
|
-
} from "./server-
|
|
37
|
+
} from "./server-fby0cxbq.js";
|
|
38
38
|
import"./server-6byqfbqf.js";
|
|
39
|
-
import"./server-
|
|
39
|
+
import"./server-09g9pkvx.js";
|
|
40
40
|
import"./server-1zx87sdm.js";
|
|
41
|
-
import"./server-
|
|
41
|
+
import"./server-yd01snxq.js";
|
|
42
42
|
import"./server-cw6521wn.js";
|
|
43
43
|
import"./server-51779zs2.js";
|
|
44
|
-
import"./server-
|
|
44
|
+
import"./server-387vkhjq.js";
|
|
45
45
|
import"./server-2ra6pwf3.js";
|
|
46
|
-
import"./server-
|
|
46
|
+
import"./server-4tn95znb.js";
|
|
47
47
|
import"./server-7ekna9zs.js";
|
|
48
48
|
import"./server-fr0wbhdn.js";
|
|
49
|
-
import"./server-
|
|
50
|
-
import"./server-
|
|
51
|
-
import"./server-
|
|
49
|
+
import"./server-ww9nr8pe.js";
|
|
50
|
+
import"./server-btgnsv7w.js";
|
|
51
|
+
import"./server-158ehmk2.js";
|
|
52
52
|
import"./server-fb3zxn06.js";
|
|
53
|
-
import"./server-
|
|
53
|
+
import"./server-x2r63c0x.js";
|
|
54
54
|
import {
|
|
55
55
|
pushNotification2
|
|
56
56
|
} from "./server-x8a7jmkh.js";
|
|
57
|
-
import"./server-
|
|
57
|
+
import"./server-6a9mxnb2.js";
|
|
58
58
|
import"./server-qt1qqasc.js";
|
|
59
59
|
import"./server-4dhv7mqz.js";
|
|
60
60
|
import"./server-ras2sxnc.js";
|
|
61
|
-
import"./server-
|
|
62
|
-
import"./server-
|
|
61
|
+
import"./server-f9py7s7a.js";
|
|
62
|
+
import"./server-cm4hmxyk.js";
|
|
63
63
|
import"./server-d6g4whc2.js";
|
|
64
64
|
import"./server-vb7pbd9p.js";
|
|
65
65
|
import"./server-t528t8qm.js";
|
|
66
66
|
import"./server-676xw7at.js";
|
|
67
67
|
import {
|
|
68
68
|
sendStatusNotification2
|
|
69
|
-
} from "./server-
|
|
69
|
+
} from "./server-9zqewm6g.js";
|
|
70
70
|
import"./server-3t0q2cqx.js";
|
|
71
71
|
|
|
72
72
|
// src/hooks/magic-context/wrapup-orchestrator.ts
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runManagedWrapup2
|
|
3
|
-
} from "./index-
|
|
4
|
-
import"./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
3
|
+
} from "./index-a796ct3s.js";
|
|
4
|
+
import"./index-ck6y3td2.js";
|
|
5
|
+
import"./index-vh3e2mvr.js";
|
|
6
|
+
import"./index-f3dnvnw6.js";
|
|
7
7
|
import"./index-sd3egckz.js";
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
8
|
+
import"./index-s0gsmthp.js";
|
|
9
|
+
import"./index-1xaw2pq8.js";
|
|
10
|
+
import"./index-7q1m1qjk.js";
|
|
11
|
+
import"./index-cm4hmxyk.js";
|
|
12
|
+
import"./index-9s58tq95.js";
|
|
13
|
+
import"./index-j55vn694.js";
|
|
14
14
|
import"./index-4dhv7mqz.js";
|
|
15
15
|
import"./index-w23dh319.js";
|
|
16
|
-
import"./index-
|
|
16
|
+
import"./index-hr64sth2.js";
|
|
17
17
|
import"./index-qt1qqasc.js";
|
|
18
18
|
import"./index-x8a7jmkh.js";
|
|
19
19
|
import"./index-tqf7yg27.js";
|
|
20
20
|
import"./index-gbmqa9x9.js";
|
|
21
21
|
import"./index-vkbqdnkj.js";
|
|
22
|
-
import"./index-
|
|
22
|
+
import"./index-besxhcsh.js";
|
|
23
23
|
import"./index-fb3zxn06.js";
|
|
24
|
-
import"./index-
|
|
25
|
-
import"./index-
|
|
24
|
+
import"./index-xqyj5c85.js";
|
|
25
|
+
import"./index-9m7bn21d.js";
|
|
26
26
|
import"./index-fr0wbhdn.js";
|
|
27
|
-
import"./index-
|
|
28
|
-
import"./index-
|
|
29
|
-
import"./index-
|
|
30
|
-
import"./index-
|
|
27
|
+
import"./index-g9exahnx.js";
|
|
28
|
+
import"./index-bg5qqene.js";
|
|
29
|
+
import"./index-vztbgcdk.js";
|
|
30
|
+
import"./index-1j8jcjpa.js";
|
|
31
31
|
import"./index-1zx87sdm.js";
|
|
32
|
-
import"./index-
|
|
33
|
-
import"./index-
|
|
32
|
+
import"./index-ab3bgm2m.js";
|
|
33
|
+
import"./index-vnjhmkwk.js";
|
|
34
34
|
import"./index-v0p37hm2.js";
|
|
35
35
|
import"./index-k6xvbj2e.js";
|
|
36
36
|
import"./index-h2wc01qk.js";
|
|
37
37
|
import"./index-1bt88epp.js";
|
|
38
38
|
import"./index-58e3y90n.js";
|
|
39
39
|
import"./index-4mjhqadz.js";
|
|
40
|
-
import"./index-
|
|
40
|
+
import"./index-0nnd4bry.js";
|
|
41
41
|
import"./index-qx53vezw.js";
|
|
42
42
|
import"./index-nsjyysj0.js";
|
|
43
43
|
import"./index-0sahzkwr.js";
|
package/package.json
CHANGED
|
@@ -118,7 +118,7 @@ test("exhausted routed acquisition never enters the callback or multiplies privi
|
|
|
118
118
|
db.close();
|
|
119
119
|
rmSync(dir, { recursive: true, force: true });
|
|
120
120
|
}
|
|
121
|
-
});
|
|
121
|
+
}, 30_000);
|
|
122
122
|
|
|
123
123
|
for (const mode of ["run", "get", "all", "exec"] as const) {
|
|
124
124
|
test(`foreground ${mode} autocommit waits share one turn budget and restore production timeout`, () => {
|
|
@@ -147,7 +147,8 @@ for (const mode of ["run", "get", "all", "exec"] as const) {
|
|
|
147
147
|
}
|
|
148
148
|
expect(() => db.exec("BEGIN IMMEDIATE")).toThrow("acquisition remained busy");
|
|
149
149
|
});
|
|
150
|
-
expect(performance.now() - started).
|
|
150
|
+
expect(performance.now() - started).toBeGreaterThanOrEqual(1900);
|
|
151
|
+
expect(performance.now() - started).toBeLessThan(2600);
|
|
151
152
|
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
152
153
|
expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
|
|
153
154
|
blocker.exec("ROLLBACK");
|
|
@@ -159,5 +160,5 @@ for (const mode of ["run", "get", "all", "exec"] as const) {
|
|
|
159
160
|
db.close();
|
|
160
161
|
rmSync(dir, { recursive: true, force: true });
|
|
161
162
|
}
|
|
162
|
-
});
|
|
163
|
+
}, 30_000);
|
|
163
164
|
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { StorageBusyRefusalError } from "../hooks/magic-context/storage-busy-refusal";
|
|
6
|
+
import { createMessagesTransformHandler } from "../plugin/messages-transform";
|
|
7
|
+
import { log } from "./logger";
|
|
8
|
+
import {
|
|
9
|
+
Database,
|
|
10
|
+
guardSqliteTransformPass,
|
|
11
|
+
registerSqliteDiagnosticSink,
|
|
12
|
+
SqliteAcquisitionBusyError,
|
|
13
|
+
withPrivilegedWriter,
|
|
14
|
+
withSqliteTransformPass,
|
|
15
|
+
} from "./sqlite";
|
|
16
|
+
import { type SqliteWriteLocker, startSqliteWriteLocker } from "./sqlite-write-locker-test-support";
|
|
17
|
+
import { createTestTempDirFromPath } from "./test-temp-dir";
|
|
18
|
+
|
|
19
|
+
function fixture() {
|
|
20
|
+
const dir = createTestTempDirFromPath(join(tmpdir(), "mc-foreground-wait-"));
|
|
21
|
+
const path = join(dir, "context.db");
|
|
22
|
+
const db = new Database(path);
|
|
23
|
+
db.exec(`
|
|
24
|
+
PRAGMA journal_mode=WAL;
|
|
25
|
+
PRAGMA busy_timeout=5000;
|
|
26
|
+
CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER);
|
|
27
|
+
CREATE TABLE result(value TEXT);
|
|
28
|
+
`);
|
|
29
|
+
return {
|
|
30
|
+
db,
|
|
31
|
+
path,
|
|
32
|
+
close() {
|
|
33
|
+
db.close();
|
|
34
|
+
rmSync(dir, { recursive: true, force: true });
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const holdMs of [1000, 2500]) {
|
|
40
|
+
test(holdMs === 1000
|
|
41
|
+
? "a transform commits and serves managed output after a 1s in-pass writer lock"
|
|
42
|
+
: "a transform refuses a 2.5s in-pass writer lock without raw fallback and logs the real wait", async () => {
|
|
43
|
+
const { db, path, close } = fixture();
|
|
44
|
+
const sessionId = `foreground-wait-${holdMs}`;
|
|
45
|
+
const output = {
|
|
46
|
+
messages: [
|
|
47
|
+
{
|
|
48
|
+
info: { id: "u", sessionID: sessionId, role: "user" },
|
|
49
|
+
parts: [{ type: "text", text: "raw input must not be served on failure" }],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
let locker: SqliteWriteLocker | undefined;
|
|
54
|
+
let refusals = 0;
|
|
55
|
+
let served = false;
|
|
56
|
+
let waitedMs = 0;
|
|
57
|
+
const diagnostics: string[] = [];
|
|
58
|
+
registerSqliteDiagnosticSink((line) => diagnostics.push(line));
|
|
59
|
+
const handler = createMessagesTransformHandler({
|
|
60
|
+
onStorageBusyRefusal: async (id) => {
|
|
61
|
+
expect(id).toBe(sessionId);
|
|
62
|
+
refusals++;
|
|
63
|
+
},
|
|
64
|
+
magicContext: {
|
|
65
|
+
"experimental.chat.messages.transform": async (_input, result) => {
|
|
66
|
+
// Start the competing writer only once the transform callback begins;
|
|
67
|
+
// otherwise the wrapper's yielding lock check would absorb the wait.
|
|
68
|
+
locker = await startSqliteWriteLocker(path, holdMs);
|
|
69
|
+
const started = performance.now();
|
|
70
|
+
try {
|
|
71
|
+
withPrivilegedWriter(db, () => {
|
|
72
|
+
db.prepare("INSERT INTO result VALUES ('managed')").run();
|
|
73
|
+
});
|
|
74
|
+
} finally {
|
|
75
|
+
waitedMs = performance.now() - started;
|
|
76
|
+
}
|
|
77
|
+
(result.messages[0].parts[0] as { text: string }).text = "managed output";
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
const pass = handler({}, output as Parameters<typeof handler>[1]).then((messages) => {
|
|
83
|
+
served = true;
|
|
84
|
+
return messages;
|
|
85
|
+
});
|
|
86
|
+
if (holdMs === 1000) {
|
|
87
|
+
await pass;
|
|
88
|
+
expect(served).toBe(true);
|
|
89
|
+
expect(refusals).toBe(0);
|
|
90
|
+
expect(output.messages[0].parts[0].text).toBe("managed output");
|
|
91
|
+
expect(db.prepare("SELECT * FROM result").all()).toEqual([{ value: "managed" }]);
|
|
92
|
+
expect(waitedMs).toBeGreaterThanOrEqual(900);
|
|
93
|
+
} else {
|
|
94
|
+
await expect(pass).rejects.toBeInstanceOf(StorageBusyRefusalError);
|
|
95
|
+
expect(served).toBe(false);
|
|
96
|
+
expect(refusals).toBe(1);
|
|
97
|
+
expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
|
|
98
|
+
expect(waitedMs).toBeGreaterThanOrEqual(1900);
|
|
99
|
+
expect(waitedMs).toBeLessThan(2400);
|
|
100
|
+
const busy = diagnostics.filter((line) => line.includes("outcome=busy"));
|
|
101
|
+
expect(busy).toHaveLength(1);
|
|
102
|
+
expect(busy[0]).toContain("lane=foreground");
|
|
103
|
+
const reportedMs = Number(/acquire_ms=(\d+)/.exec(busy[0])?.[1]);
|
|
104
|
+
expect(Math.abs(reportedMs - waitedMs)).toBeLessThan(100);
|
|
105
|
+
}
|
|
106
|
+
expect(db.inTransaction).toBe(false);
|
|
107
|
+
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
108
|
+
} finally {
|
|
109
|
+
registerSqliteDiagnosticSink(log);
|
|
110
|
+
if (locker) expect(await locker.exited).toBe(0);
|
|
111
|
+
close();
|
|
112
|
+
}
|
|
113
|
+
}, 30_000);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const mode of ["BEGIN", "autocommit"]) {
|
|
117
|
+
test(`foreground ${mode} wait is capped by the pass deadline`, () => {
|
|
118
|
+
const { db, path, close } = fixture();
|
|
119
|
+
const blocker = new Database(path);
|
|
120
|
+
blocker.exec("BEGIN IMMEDIATE");
|
|
121
|
+
try {
|
|
122
|
+
const started = performance.now();
|
|
123
|
+
withSqliteTransformPass(() => {
|
|
124
|
+
guardSqliteTransformPass({ assert() {}, remainingMs: () => 100 });
|
|
125
|
+
expect(() => {
|
|
126
|
+
if (mode === "BEGIN") withPrivilegedWriter(db, () => undefined);
|
|
127
|
+
else db.prepare("INSERT INTO result VALUES ('late')").run();
|
|
128
|
+
}).toThrow(SqliteAcquisitionBusyError);
|
|
129
|
+
});
|
|
130
|
+
expect(performance.now() - started).toBeGreaterThanOrEqual(75);
|
|
131
|
+
expect(performance.now() - started).toBeLessThan(700);
|
|
132
|
+
expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
|
|
133
|
+
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
134
|
+
} finally {
|
|
135
|
+
blocker.exec("ROLLBACK");
|
|
136
|
+
blocker.close();
|
|
137
|
+
close();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
@@ -100,7 +100,7 @@ test("foreground admission keeps the loop ticking while a separate writer holds
|
|
|
100
100
|
}
|
|
101
101
|
}, 30000);
|
|
102
102
|
|
|
103
|
-
test("a foreground in-pass writer has bounded
|
|
103
|
+
test("a foreground in-pass writer has bounded 2000ms tolerance and restores its timeout", () => {
|
|
104
104
|
const { db, path, close } = fixture();
|
|
105
105
|
const blocker = new Database(path);
|
|
106
106
|
blocker.exec("BEGIN IMMEDIATE");
|
|
@@ -109,15 +109,15 @@ test("a foreground in-pass writer has bounded 250ms tolerance and restores its t
|
|
|
109
109
|
expect(() =>
|
|
110
110
|
withSqliteTransformPass(() => withPrivilegedWriter(db, () => undefined)),
|
|
111
111
|
).toThrow(SqliteAcquisitionBusyError);
|
|
112
|
-
expect(performance.now() - start).toBeGreaterThanOrEqual(
|
|
113
|
-
expect(performance.now() - start).toBeLessThan(
|
|
112
|
+
expect(performance.now() - start).toBeGreaterThanOrEqual(1900);
|
|
113
|
+
expect(performance.now() - start).toBeLessThan(2500);
|
|
114
114
|
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
115
115
|
} finally {
|
|
116
116
|
blocker.exec("ROLLBACK");
|
|
117
117
|
blocker.close();
|
|
118
118
|
close();
|
|
119
119
|
}
|
|
120
|
-
});
|
|
120
|
+
}, 30000);
|
|
121
121
|
|
|
122
122
|
test("ready background publication retries on a timer and retains its write", async () => {
|
|
123
123
|
const { db, path, close } = fixture();
|
package/src/shared/sqlite.ts
CHANGED
|
@@ -940,7 +940,7 @@ export class SqliteAcquisitionBusyError extends Error {
|
|
|
940
940
|
}
|
|
941
941
|
|
|
942
942
|
const SHORT_BUSY_TIMEOUT_MS = 25;
|
|
943
|
-
const FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS =
|
|
943
|
+
const FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 2_000;
|
|
944
944
|
const FOREGROUND_ACQUISITION_BUDGET_MS = 16_500;
|
|
945
945
|
/** Waiting this long for the writer lock, or holding it this long, is logged. */
|
|
946
946
|
const SLOW_WRITER_LOG_MS = 250;
|
|
@@ -994,7 +994,7 @@ function withAutocommitTimeout<T>(db: Database, operation: () => T): T {
|
|
|
994
994
|
if (isInTransaction(db) || (!lease && !backgroundWriterScope.getStore())) return operation();
|
|
995
995
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
996
996
|
db.exec(
|
|
997
|
-
`PRAGMA busy_timeout=${lease ? Math.floor(lease.remainingWaitMs) : SHORT_BUSY_TIMEOUT_MS}`,
|
|
997
|
+
`PRAGMA busy_timeout=${lease ? Math.floor(Math.min(lease.remainingWaitMs, lease.guard?.remainingMs() ?? Infinity)) : SHORT_BUSY_TIMEOUT_MS}`,
|
|
998
998
|
);
|
|
999
999
|
const started = performance.now();
|
|
1000
1000
|
try {
|