@retaw106/mmc-pi 1.2.3 → 2.1.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 +23 -6
- package/dist/cli.js +7095 -0
- package/dist/config-init.js +5595 -0
- package/dist/{index-ztb4k1mt.js → index-4n1w7ehq.js} +4244 -3960
- package/dist/{index-65ee50rm.js → index-dx9vhsy8.js} +3 -2
- package/dist/{index-wv28nczk.js → index-ny303arh.js} +76 -3
- package/dist/index.js +3319 -2081
- package/dist/{message-time-backfill-h02fzzp8.js → message-time-backfill-a3p9r5rh.js} +2 -2
- package/dist/{read-session-chunk-af3sdznq.js → read-session-chunk-7wcjah1z.js} +2 -2
- package/dist/web/main.js +1555 -203
- package/dist/web/ui/index.html +1 -0
- package/dist/web/ui/panel.css +7 -0
- package/dist/web/ui/panel.js +332 -124
- package/package.json +7 -2
|
@@ -4,12 +4,13 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// ../plugin/src/shared/write-transaction-timing.ts
|
|
6
6
|
var SLOW_WRITE_TRANSACTION_THRESHOLD_MS = 1000;
|
|
7
|
-
function logSlowWriteTransaction(site, startedAt, thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS, completedAtMs = performance.now()) {
|
|
7
|
+
function logSlowWriteTransaction(site, startedAt, thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS, completedAtMs = performance.now(), steps) {
|
|
8
8
|
try {
|
|
9
9
|
const durationMs = completedAtMs - startedAt;
|
|
10
10
|
if (durationMs < thresholdMs)
|
|
11
11
|
return;
|
|
12
|
-
|
|
12
|
+
const detail = steps ? Object.entries(steps).map(([name, ms]) => `${name}=${ms.toFixed(1)}ms`).join(" ") : "";
|
|
13
|
+
log(`[magic-context] slow write transaction: site=${site} held=${durationMs.toFixed(1)}ms${detail ? ` ${detail}` : ""}`);
|
|
13
14
|
} catch {}
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -69,6 +69,8 @@ function installTransactionRouting(db, readonly) {
|
|
|
69
69
|
configurable: true,
|
|
70
70
|
writable: true,
|
|
71
71
|
value: (sql) => {
|
|
72
|
+
if (/^\s*(?:COMMIT|END)\b/i.test(sql))
|
|
73
|
+
assertTransformWrite();
|
|
72
74
|
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
73
75
|
openWriterTransactions.delete(db);
|
|
74
76
|
if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore())
|
|
@@ -221,6 +223,15 @@ function pragmaNumber(db, name) {
|
|
|
221
223
|
}
|
|
222
224
|
var statementOwners = new WeakMap;
|
|
223
225
|
var FIRST_PRUNE_AT = 256;
|
|
226
|
+
function closeReleasingStatements(close, args) {
|
|
227
|
+
if (args[0] === true)
|
|
228
|
+
return close(true);
|
|
229
|
+
try {
|
|
230
|
+
return close(true);
|
|
231
|
+
} catch {
|
|
232
|
+
return close(...args);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
224
235
|
function ownPreparedStatement(db, statement) {
|
|
225
236
|
const finalizable = statement;
|
|
226
237
|
if (typeof finalizable.finalize !== "function")
|
|
@@ -244,7 +255,7 @@ function ownPreparedStatement(db, statement) {
|
|
|
244
255
|
}
|
|
245
256
|
}
|
|
246
257
|
references.clear();
|
|
247
|
-
const result = close
|
|
258
|
+
const result = closeReleasingStatements(close, args);
|
|
248
259
|
if (failure)
|
|
249
260
|
throw failure;
|
|
250
261
|
return result;
|
|
@@ -298,6 +309,15 @@ function withSqliteTransformPass(operation) {
|
|
|
298
309
|
function withoutSqliteTransformPass(operation) {
|
|
299
310
|
return transformPassScope.run(undefined, operation);
|
|
300
311
|
}
|
|
312
|
+
function guardSqliteTransformPass(guard) {
|
|
313
|
+
const lease = transformPassScope.getStore();
|
|
314
|
+
if (lease)
|
|
315
|
+
lease.guard = guard;
|
|
316
|
+
}
|
|
317
|
+
function assertTransformWrite() {
|
|
318
|
+
if (!backgroundWriterScope.getStore())
|
|
319
|
+
transformPassScope.getStore()?.guard?.assert();
|
|
320
|
+
}
|
|
301
321
|
function isTransientSqliteError(error) {
|
|
302
322
|
if (!error || typeof error !== "object")
|
|
303
323
|
return false;
|
|
@@ -316,6 +336,7 @@ class SqliteAcquisitionBusyError extends Error {
|
|
|
316
336
|
}
|
|
317
337
|
var SHORT_BUSY_TIMEOUT_MS = 25;
|
|
318
338
|
var FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 250;
|
|
339
|
+
var FOREGROUND_ACQUISITION_BUDGET_MS = 16500;
|
|
319
340
|
var SLOW_WRITER_LOG_MS = 250;
|
|
320
341
|
var WRITER_TRANSACTION_END = /^\s*(?:COMMIT|END|ROLLBACK)(?:\s+TRANSACTION)?\s*;?\s*$/i;
|
|
321
342
|
var writerAcquisitionScope = new AsyncLocalStorage;
|
|
@@ -325,6 +346,7 @@ function foregroundWaitLease() {
|
|
|
325
346
|
return lease?.active && !admissionScope.getStore() && !backgroundWriterScope.getStore() ? lease : undefined;
|
|
326
347
|
}
|
|
327
348
|
function withAutocommitTimeout(db, operation) {
|
|
349
|
+
assertTransformWrite();
|
|
328
350
|
const lease = foregroundWaitLease();
|
|
329
351
|
if (isInTransaction(db) || !lease && !backgroundWriterScope.getStore())
|
|
330
352
|
return operation();
|
|
@@ -345,6 +367,7 @@ function withAutocommitTimeout(db, operation) {
|
|
|
345
367
|
}
|
|
346
368
|
}
|
|
347
369
|
function acquireShort(db, acquire, site) {
|
|
370
|
+
assertTransformWrite();
|
|
348
371
|
const started = performance.now();
|
|
349
372
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
350
373
|
const outer = writerAcquisitionScope.getStore();
|
|
@@ -356,7 +379,7 @@ function acquireShort(db, acquire, site) {
|
|
|
356
379
|
let acquiredAt;
|
|
357
380
|
try {
|
|
358
381
|
const lease = foregroundWaitLease();
|
|
359
|
-
const timeout =
|
|
382
|
+
const timeout = Math.floor(Math.min(lease ? lease.remainingWaitMs : SHORT_BUSY_TIMEOUT_MS, owner?.remainingMs?.() ?? lease?.guard?.remainingMs() ?? Infinity));
|
|
360
383
|
db.exec(`PRAGMA busy_timeout=${timeout}`);
|
|
361
384
|
acquire();
|
|
362
385
|
acquiredAt = performance.now();
|
|
@@ -402,6 +425,56 @@ function endWriterTransaction(db, end, sql) {
|
|
|
402
425
|
}
|
|
403
426
|
}
|
|
404
427
|
}
|
|
428
|
+
async function withAsyncPrivilegedWriter(db, operation, options = {}) {
|
|
429
|
+
const started = performance.now();
|
|
430
|
+
const budgetMs = Math.max(0, Math.min(FOREGROUND_ACQUISITION_BUDGET_MS, options.budgetMs ?? Infinity));
|
|
431
|
+
let attempts = 0;
|
|
432
|
+
for (;; ) {
|
|
433
|
+
options.signal?.throwIfAborted();
|
|
434
|
+
options.assertCurrentPass?.();
|
|
435
|
+
attempts++;
|
|
436
|
+
let entered = false;
|
|
437
|
+
try {
|
|
438
|
+
const acquisition = {
|
|
439
|
+
site: "privileged_writer",
|
|
440
|
+
lane: "foreground",
|
|
441
|
+
startedAt: started,
|
|
442
|
+
attempts,
|
|
443
|
+
claimed: false,
|
|
444
|
+
remainingMs: () => Math.max(0, budgetMs - (performance.now() - started))
|
|
445
|
+
};
|
|
446
|
+
return admissionScope.run(true, () => withSqliteTransformPass(() => writerAcquisitionScope.run(acquisition, () => withPrivilegedWriter(db, () => {
|
|
447
|
+
entered = true;
|
|
448
|
+
return operation();
|
|
449
|
+
}))));
|
|
450
|
+
} catch (error) {
|
|
451
|
+
if (entered || !(error instanceof SqliteAcquisitionBusyError))
|
|
452
|
+
throw error;
|
|
453
|
+
options.beforeRetry?.(error);
|
|
454
|
+
const elapsed = performance.now() - started;
|
|
455
|
+
if (elapsed >= budgetMs) {
|
|
456
|
+
reportSqliteDiagnostic(`sqlite writer site=privileged_writer lane=foreground acquire_ms=${Math.round(elapsed)} attempts=${attempts} outcome=busy`);
|
|
457
|
+
throw error;
|
|
458
|
+
}
|
|
459
|
+
const backoff = attempts === 1 ? 500 : 1000;
|
|
460
|
+
const delay = Math.min(options.jitter ? backoff * (0.8 + Math.random() * 0.4) : backoff, budgetMs - elapsed);
|
|
461
|
+
await new Promise((resolve, reject) => {
|
|
462
|
+
const abort = () => {
|
|
463
|
+
clearTimeout(timer);
|
|
464
|
+
options.signal?.removeEventListener("abort", abort);
|
|
465
|
+
reject(options.signal?.reason ?? new Error("Writer wait aborted"));
|
|
466
|
+
};
|
|
467
|
+
const timer = setTimeout(() => {
|
|
468
|
+
options.signal?.removeEventListener("abort", abort);
|
|
469
|
+
resolve();
|
|
470
|
+
}, delay);
|
|
471
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
472
|
+
if (options.signal?.aborted)
|
|
473
|
+
abort();
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
405
478
|
function isInTransaction(db) {
|
|
406
479
|
const candidate = db;
|
|
407
480
|
return candidate.inTransaction === true || candidate.isTransaction === true;
|
|
@@ -461,4 +534,4 @@ function withPrivilegedWriter(db, operation) {
|
|
|
461
534
|
}
|
|
462
535
|
}
|
|
463
536
|
|
|
464
|
-
export { registerSlowWriteReporter, registerSqliteDiagnosticSink, detectSqliteRuntime, Database, prepareCachedStatement, withSqliteBackgroundWriter, withSqliteTransformPass, withoutSqliteTransformPass, isTransientSqliteError, withPrivilegedWriter };
|
|
537
|
+
export { registerSlowWriteReporter, registerSqliteDiagnosticSink, detectSqliteRuntime, Database, prepareCachedStatement, withSqliteBackgroundWriter, withSqliteTransformPass, withoutSqliteTransformPass, guardSqliteTransformPass, isTransientSqliteError, withAsyncPrivilegedWriter, withPrivilegedWriter };
|