@noy-db/hub 0.2.0-pre.25 → 0.2.0-pre.27
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/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +1 -1
- package/dist/attestation/index.d.ts +1 -1
- package/dist/attestation/index.js +4 -4
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +3 -3
- package/dist/blobs/index.d.ts +3 -3
- package/dist/blobs/index.js +4 -4
- package/dist/bundle/index.cjs +320 -144
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +3 -3
- package/dist/bundle/index.d.ts +3 -3
- package/dist/bundle/index.js +8 -8
- package/dist/{chunk-HUXDQIVU.js → chunk-2NYVA6FW.js} +2 -2
- package/dist/{chunk-OCRDV3NU.js → chunk-5EITJMUJ.js} +3 -3
- package/dist/{chunk-EYZJULEN.js → chunk-6H4CAHMQ.js} +2 -2
- package/dist/{chunk-VGAN5RLD.js → chunk-6M5JKTUQ.js} +2 -2
- package/dist/{chunk-N4EXCKWP.js → chunk-6ZKXFMUG.js} +2 -2
- package/dist/{chunk-KJ37E3R5.js → chunk-7DDTFGXY.js} +2 -2
- package/dist/{chunk-LR7CODVN.js → chunk-AD6RNBAW.js} +1 -1
- package/dist/chunk-AD6RNBAW.js.map +1 -0
- package/dist/{chunk-TSUICI5N.js → chunk-BMDVFBCL.js} +2 -2
- package/dist/{chunk-FCIZXX56.js → chunk-BOMH3637.js} +2 -2
- package/dist/{chunk-RZOGD7IF.js → chunk-CVTPNW2Y.js} +6 -6
- package/dist/{chunk-GPZHHTJU.js → chunk-DONPLWRC.js} +2 -2
- package/dist/{chunk-GHXOVGTX.js → chunk-HAKEZTA7.js} +3 -3
- package/dist/{chunk-QYQRAOEF.js → chunk-I2RX62RX.js} +2 -2
- package/dist/{chunk-2RHBFCWQ.js → chunk-IWGVH2RR.js} +3 -3
- package/dist/{chunk-Y5CTT6K5.js → chunk-K6PCTYAH.js} +2 -2
- package/dist/{chunk-ANLOD6IS.js → chunk-KA5A5CSD.js} +3 -3
- package/dist/{chunk-56ENKU46.js → chunk-KSKKLVPA.js} +97 -144
- package/dist/chunk-KSKKLVPA.js.map +1 -0
- package/dist/{chunk-UNBX2HMA.js → chunk-LXA2E3VI.js} +2 -2
- package/dist/{chunk-JJKXJAH2.js → chunk-PFKAT4NT.js} +3 -3
- package/dist/{chunk-ZCBJIDT4.js → chunk-RRCRITDM.js} +2 -2
- package/dist/{chunk-YP2AYE5W.js → chunk-SID2NJNF.js} +2 -2
- package/dist/chunk-Z3BJF7SF.js +220 -0
- package/dist/chunk-Z3BJF7SF.js.map +1 -0
- package/dist/consent/index.d.cts +2 -2
- package/dist/consent/index.d.ts +2 -2
- package/dist/{decrypt-partition-CyyJUWLR.d.ts → decrypt-partition-CptDdcCx.d.ts} +1 -1
- package/dist/{decrypt-partition-C71vhnND.d.cts → decrypt-partition-DmkeOB4I.d.cts} +1 -1
- package/dist/derivations/index.d.cts +3 -3
- package/dist/derivations/index.d.ts +3 -3
- package/dist/{dev-unlock-BdrE0kbS.d.cts → dev-unlock-DUTLA3Sc.d.cts} +1 -1
- package/dist/{dev-unlock-ByBkl99-.d.ts → dev-unlock-Y9znMkQ2.d.ts} +1 -1
- package/dist/{fanout-sidecar-ZQT4Y7PF.js → fanout-sidecar-OC4QVTS2.js} +2 -2
- package/dist/forget/index.js +2 -2
- package/dist/guards/index.d.cts +3 -3
- package/dist/guards/index.d.ts +3 -3
- package/dist/{hash-CZxVv8RH.d.ts → hash-Btl9IvQS.d.ts} +1 -1
- package/dist/{hash-BUkDp_8Q.d.cts → hash-DFK7cGdo.d.cts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +3 -3
- package/dist/history/index.d.ts +3 -3
- package/dist/history/index.js +3 -3
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +2 -2
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +3 -3
- package/dist/{index-CBUhOmrM.d.cts → index-CqzZml-D.d.cts} +1 -1
- package/dist/{index-DFhKV-6A.d.ts → index-wRwJVVJQ.d.ts} +1 -1
- package/dist/index.cjs +316 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/{issue-LEBPVF3Y.js → issue-ZZ2XPOGP.js} +4 -4
- package/dist/kernel/index.cjs +61 -0
- package/dist/kernel/index.cjs.map +1 -1
- package/dist/kernel/index.d.cts +2 -2
- package/dist/kernel/index.d.ts +2 -2
- package/dist/kernel/index.js +7 -0
- package/dist/{ledger-FLRTSOYH.js → ledger-XQ4KVFQ6.js} +3 -3
- package/dist/materialized-views/index.d.cts +3 -3
- package/dist/materialized-views/index.d.ts +3 -3
- package/dist/{mime-magic-BAhLjkHw.d.cts → mime-magic-Co4Pyj-O.d.cts} +1 -1
- package/dist/{mime-magic-C1UbcBxP.d.ts → mime-magic-OiPT1qed.d.ts} +1 -1
- package/dist/{noydb-6FA46A4M.js → noydb-EY52NVH4.js} +15 -14
- package/dist/overlay-views/index.d.cts +3 -3
- package/dist/overlay-views/index.d.ts +3 -3
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +2 -2
- package/dist/periods/index.d.ts +2 -2
- package/dist/periods/index.js +3 -3
- package/dist/{public-envelope-DBKJEBBF.js → public-envelope-O6X6AUUS.js} +3 -3
- package/dist/{revoke-P5D3UTRX.js → revoke-QJ2HUM4W.js} +4 -4
- package/dist/session/index.d.cts +3 -3
- package/dist/session/index.d.ts +3 -3
- package/dist/shadow/index.d.cts +2 -2
- package/dist/shadow/index.d.ts +2 -2
- package/dist/{signer-NEQPCHMW.js → signer-SCJ6C6HQ.js} +3 -3
- package/dist/snapshots/index.d.cts +2 -2
- package/dist/snapshots/index.d.ts +2 -2
- package/dist/snapshots/index.js +3 -3
- package/dist/store/index.d.cts +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +2 -2
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +2 -2
- package/dist/team/index.d.ts +2 -2
- package/dist/team/index.js +5 -5
- package/dist/{transition-guard-BSLdikC_.d.ts → transition-guard-CJmb8O8q.d.ts} +1 -1
- package/dist/{transition-guard-DPs6al8h.d.cts → transition-guard-Dzj68JWC.d.cts} +1 -1
- package/dist/tx/index.d.cts +2 -2
- package/dist/tx/index.d.ts +2 -2
- package/dist/{types-CCq0WHh9.d.ts → types-CkSWJt0H.d.ts} +137 -7
- package/dist/{types-BCYvhKzr.d.cts → types-CwrTuYFI.d.cts} +137 -7
- package/dist/{with-materialized-view-DiD41wQp.d.ts → with-materialized-view-BVfcPlaE.d.ts} +1 -1
- package/dist/{with-materialized-view-CTHe6uh9.d.cts → with-materialized-view-dPG213gd.d.cts} +1 -1
- package/dist/{with-overlayed-view-Dlz5hcM8.d.cts → with-overlayed-view-CJ2UDBol.d.cts} +1 -1
- package/dist/{with-overlayed-view-DlbsJMhF.d.ts → with-overlayed-view-zYPQzGGh.d.ts} +1 -1
- package/dist/{with-rollup-BBWdrCvu.d.cts → with-rollup-B_zbRi3f.d.cts} +1 -1
- package/dist/{with-rollup-mT4_CWaU.d.ts → with-rollup-BvaJefEs.d.ts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-56ENKU46.js.map +0 -1
- package/dist/chunk-LR7CODVN.js.map +0 -1
- /package/dist/{chunk-HUXDQIVU.js.map → chunk-2NYVA6FW.js.map} +0 -0
- /package/dist/{chunk-OCRDV3NU.js.map → chunk-5EITJMUJ.js.map} +0 -0
- /package/dist/{chunk-EYZJULEN.js.map → chunk-6H4CAHMQ.js.map} +0 -0
- /package/dist/{chunk-VGAN5RLD.js.map → chunk-6M5JKTUQ.js.map} +0 -0
- /package/dist/{chunk-N4EXCKWP.js.map → chunk-6ZKXFMUG.js.map} +0 -0
- /package/dist/{chunk-KJ37E3R5.js.map → chunk-7DDTFGXY.js.map} +0 -0
- /package/dist/{chunk-TSUICI5N.js.map → chunk-BMDVFBCL.js.map} +0 -0
- /package/dist/{chunk-FCIZXX56.js.map → chunk-BOMH3637.js.map} +0 -0
- /package/dist/{chunk-RZOGD7IF.js.map → chunk-CVTPNW2Y.js.map} +0 -0
- /package/dist/{chunk-GPZHHTJU.js.map → chunk-DONPLWRC.js.map} +0 -0
- /package/dist/{chunk-GHXOVGTX.js.map → chunk-HAKEZTA7.js.map} +0 -0
- /package/dist/{chunk-QYQRAOEF.js.map → chunk-I2RX62RX.js.map} +0 -0
- /package/dist/{chunk-2RHBFCWQ.js.map → chunk-IWGVH2RR.js.map} +0 -0
- /package/dist/{chunk-Y5CTT6K5.js.map → chunk-K6PCTYAH.js.map} +0 -0
- /package/dist/{chunk-ANLOD6IS.js.map → chunk-KA5A5CSD.js.map} +0 -0
- /package/dist/{chunk-UNBX2HMA.js.map → chunk-LXA2E3VI.js.map} +0 -0
- /package/dist/{chunk-JJKXJAH2.js.map → chunk-PFKAT4NT.js.map} +0 -0
- /package/dist/{chunk-ZCBJIDT4.js.map → chunk-RRCRITDM.js.map} +0 -0
- /package/dist/{chunk-YP2AYE5W.js.map → chunk-SID2NJNF.js.map} +0 -0
- /package/dist/{fanout-sidecar-ZQT4Y7PF.js.map → fanout-sidecar-OC4QVTS2.js.map} +0 -0
- /package/dist/{issue-LEBPVF3Y.js.map → issue-ZZ2XPOGP.js.map} +0 -0
- /package/dist/{ledger-FLRTSOYH.js.map → ledger-XQ4KVFQ6.js.map} +0 -0
- /package/dist/{noydb-6FA46A4M.js.map → noydb-EY52NVH4.js.map} +0 -0
- /package/dist/{public-envelope-DBKJEBBF.js.map → public-envelope-O6X6AUUS.js.map} +0 -0
- /package/dist/{revoke-P5D3UTRX.js.map → revoke-QJ2HUM4W.js.map} +0 -0
- /package/dist/{signer-NEQPCHMW.js.map → signer-SCJ6C6HQ.js.map} +0 -0
package/dist/blobs/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { B as BlobStrategy } from '../types-
|
|
2
|
-
export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-
|
|
3
|
-
export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-
|
|
1
|
+
import { B as BlobStrategy } from '../types-CwrTuYFI.cjs';
|
|
2
|
+
export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-CwrTuYFI.cjs';
|
|
3
|
+
export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-Co4Pyj-O.cjs';
|
|
4
4
|
import '../lazy-builder-eYZzLEL1.cjs';
|
|
5
5
|
import '../predicate-BmhBSPCH.cjs';
|
|
6
6
|
import '../strategy-D1zjEV3n.cjs';
|
package/dist/blobs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { B as BlobStrategy } from '../types-
|
|
2
|
-
export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-
|
|
3
|
-
export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-
|
|
1
|
+
import { B as BlobStrategy } from '../types-CkSWJt0H.js';
|
|
2
|
+
export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-CkSWJt0H.js';
|
|
3
|
+
export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-OiPT1qed.js';
|
|
4
4
|
import '../lazy-builder-ChSqcF5t.js';
|
|
5
5
|
import '../predicate-BmhBSPCH.js';
|
|
6
6
|
import '../strategy-YQ1qJWyq.js';
|
package/dist/blobs/index.js
CHANGED
|
@@ -11,16 +11,16 @@ import {
|
|
|
11
11
|
importExternalObjects,
|
|
12
12
|
isPreCompressed,
|
|
13
13
|
memoryObjectProjection
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-7DDTFGXY.js";
|
|
15
15
|
import {
|
|
16
16
|
BLOB_EVICTION_AUDIT_COLLECTION,
|
|
17
17
|
EXPORT_AUDIT_COLLECTION,
|
|
18
18
|
ExportBlobsAbortedError,
|
|
19
19
|
createExportBlobsHandle,
|
|
20
20
|
runCompaction
|
|
21
|
-
} from "../chunk-
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
21
|
+
} from "../chunk-RRCRITDM.js";
|
|
22
|
+
import "../chunk-K6PCTYAH.js";
|
|
23
|
+
import "../chunk-AD6RNBAW.js";
|
|
24
24
|
import "../chunk-7JSP3E67.js";
|
|
25
25
|
import "../chunk-DDOYOMAD.js";
|
|
26
26
|
|
package/dist/bundle/index.cjs
CHANGED
|
@@ -4353,9 +4353,252 @@ var init_peer_recover = __esm({
|
|
|
4353
4353
|
}
|
|
4354
4354
|
});
|
|
4355
4355
|
|
|
4356
|
+
// src/coordination/types.ts
|
|
4357
|
+
function isQuorum(writers, generation, excludeWriterId) {
|
|
4358
|
+
return writers.filter((w) => w.writerId !== excludeWriterId).every((w) => w.quiescedAtVersion === generation);
|
|
4359
|
+
}
|
|
4360
|
+
async function runDrainBarrier(provider, o, run) {
|
|
4361
|
+
await provider.setFence(o.vault, { currentSchemaVersion: o.generation, fenceState: "draining" });
|
|
4362
|
+
await o.onFlush();
|
|
4363
|
+
const deadline = o.now() + o.quiesceTimeoutMs;
|
|
4364
|
+
const seeded = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
|
|
4365
|
+
if (!isQuorum(seeded, o.generation, o.writerId)) {
|
|
4366
|
+
await new Promise((resolve, reject) => {
|
|
4367
|
+
let settled = false;
|
|
4368
|
+
const finish = (fn) => {
|
|
4369
|
+
if (!settled) {
|
|
4370
|
+
settled = true;
|
|
4371
|
+
unsub();
|
|
4372
|
+
fn();
|
|
4373
|
+
}
|
|
4374
|
+
};
|
|
4375
|
+
const unsub = provider.observePresence(o.vault, (writers) => {
|
|
4376
|
+
if (isQuorum(writers, o.generation, o.writerId)) finish(resolve);
|
|
4377
|
+
});
|
|
4378
|
+
const tick = async () => {
|
|
4379
|
+
if (settled) return;
|
|
4380
|
+
if (o.now() >= deadline) {
|
|
4381
|
+
finish(
|
|
4382
|
+
() => reject(
|
|
4383
|
+
new QuiesceTimeoutError(
|
|
4384
|
+
`Cutover of vault "${o.vault}" to generation ${o.generation} timed out after ${o.quiesceTimeoutMs}ms waiting for active writers to quiesce.`
|
|
4385
|
+
)
|
|
4386
|
+
)
|
|
4387
|
+
);
|
|
4388
|
+
return;
|
|
4389
|
+
}
|
|
4390
|
+
if (o.onPoll) await o.onPoll();
|
|
4391
|
+
const w = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
|
|
4392
|
+
if (isQuorum(w, o.generation, o.writerId)) finish(resolve);
|
|
4393
|
+
else setTimeout(() => void tick(), 25);
|
|
4394
|
+
};
|
|
4395
|
+
void tick();
|
|
4396
|
+
});
|
|
4397
|
+
}
|
|
4398
|
+
await run();
|
|
4399
|
+
}
|
|
4400
|
+
var init_types3 = __esm({
|
|
4401
|
+
"src/coordination/types.ts"() {
|
|
4402
|
+
"use strict";
|
|
4403
|
+
init_errors();
|
|
4404
|
+
}
|
|
4405
|
+
});
|
|
4406
|
+
|
|
4407
|
+
// src/schema-update/fence.ts
|
|
4408
|
+
async function loadFence(store, vault) {
|
|
4409
|
+
const envelope = await store.get(vault, META_COLLECTION2, FENCE_RECORD_ID);
|
|
4410
|
+
if (!envelope) return DEFAULT_FENCE;
|
|
4411
|
+
try {
|
|
4412
|
+
const parsed = JSON.parse(envelope._data);
|
|
4413
|
+
if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
|
|
4414
|
+
return parsed;
|
|
4415
|
+
} catch {
|
|
4416
|
+
return DEFAULT_FENCE;
|
|
4417
|
+
}
|
|
4418
|
+
}
|
|
4419
|
+
async function saveFence(store, vault, fence) {
|
|
4420
|
+
const envelope = {
|
|
4421
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
4422
|
+
_v: 1,
|
|
4423
|
+
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4424
|
+
_iv: "",
|
|
4425
|
+
_data: JSON.stringify(fence)
|
|
4426
|
+
};
|
|
4427
|
+
await store.put(vault, META_COLLECTION2, FENCE_RECORD_ID, envelope);
|
|
4428
|
+
}
|
|
4429
|
+
function isFenceDoc(x) {
|
|
4430
|
+
if (x === null || typeof x !== "object") return false;
|
|
4431
|
+
const o = x;
|
|
4432
|
+
return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
|
|
4433
|
+
}
|
|
4434
|
+
var FENCE_RECORD_ID, META_COLLECTION2, DEFAULT_FENCE;
|
|
4435
|
+
var init_fence = __esm({
|
|
4436
|
+
"src/schema-update/fence.ts"() {
|
|
4437
|
+
"use strict";
|
|
4438
|
+
init_types();
|
|
4439
|
+
FENCE_RECORD_ID = "schema-fence";
|
|
4440
|
+
META_COLLECTION2 = "_meta";
|
|
4441
|
+
DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
|
|
4442
|
+
}
|
|
4443
|
+
});
|
|
4444
|
+
|
|
4445
|
+
// src/schema-update/client-registry.ts
|
|
4446
|
+
async function writeClientDoc(store, vault, clientId, doc) {
|
|
4447
|
+
const envelope = {
|
|
4448
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
4449
|
+
_v: 1,
|
|
4450
|
+
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4451
|
+
_iv: "",
|
|
4452
|
+
_data: JSON.stringify({ clientId, ...doc })
|
|
4453
|
+
};
|
|
4454
|
+
await store.put(vault, META_COLLECTION3, `${CLIENT_PREFIX}${clientId}`, envelope);
|
|
4455
|
+
}
|
|
4456
|
+
async function listClientDocs(store, vault) {
|
|
4457
|
+
const ids = await store.list(vault, META_COLLECTION3);
|
|
4458
|
+
const out = [];
|
|
4459
|
+
for (const id of ids) {
|
|
4460
|
+
if (!id.startsWith(CLIENT_PREFIX)) continue;
|
|
4461
|
+
const env = await store.get(vault, META_COLLECTION3, id);
|
|
4462
|
+
if (!env) continue;
|
|
4463
|
+
try {
|
|
4464
|
+
const parsed = JSON.parse(env._data);
|
|
4465
|
+
if (isClientDoc(parsed)) out.push(parsed);
|
|
4466
|
+
} catch {
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
return out;
|
|
4470
|
+
}
|
|
4471
|
+
function isClientDoc(x) {
|
|
4472
|
+
if (x === null || typeof x !== "object") return false;
|
|
4473
|
+
const o = x;
|
|
4474
|
+
return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number") && (o["sessionId"] === void 0 || typeof o["sessionId"] === "string");
|
|
4475
|
+
}
|
|
4476
|
+
var META_COLLECTION3, CLIENT_PREFIX;
|
|
4477
|
+
var init_client_registry = __esm({
|
|
4478
|
+
"src/schema-update/client-registry.ts"() {
|
|
4479
|
+
"use strict";
|
|
4480
|
+
init_types();
|
|
4481
|
+
META_COLLECTION3 = "_meta";
|
|
4482
|
+
CLIENT_PREFIX = "schema-fence:client:";
|
|
4483
|
+
}
|
|
4484
|
+
});
|
|
4485
|
+
|
|
4486
|
+
// src/coordination/store-provider.ts
|
|
4487
|
+
function toPresence(doc) {
|
|
4488
|
+
return {
|
|
4489
|
+
writerId: doc.clientId,
|
|
4490
|
+
// Pre-#469 docs (and explicit empty) have no session — fall back to the
|
|
4491
|
+
// writerId so every presence is session-addressable.
|
|
4492
|
+
sessionId: doc.sessionId && doc.sessionId.length > 0 ? doc.sessionId : doc.clientId,
|
|
4493
|
+
lastSeen: doc.lastSeen,
|
|
4494
|
+
quiescedAtVersion: doc.quiescedAtVersion
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
4497
|
+
function fenceEqual(a, b) {
|
|
4498
|
+
return a.currentSchemaVersion === b.currentSchemaVersion && a.fenceState === b.fenceState;
|
|
4499
|
+
}
|
|
4500
|
+
function presenceListEqual(a, b) {
|
|
4501
|
+
if (a.length !== b.length) return false;
|
|
4502
|
+
const key = (w) => `${w.writerId}\0${w.sessionId}\0${w.lastSeen}\0${String(w.quiescedAtVersion)}`;
|
|
4503
|
+
const bk = new Set(b.map(key));
|
|
4504
|
+
return a.every((w) => bk.has(key(w)));
|
|
4505
|
+
}
|
|
4506
|
+
function unref(timer) {
|
|
4507
|
+
const t = timer;
|
|
4508
|
+
if (typeof t.unref === "function") t.unref();
|
|
4509
|
+
}
|
|
4510
|
+
var DEFAULT_POLL_INTERVAL_MS, StoreCoordinationProvider;
|
|
4511
|
+
var init_store_provider = __esm({
|
|
4512
|
+
"src/coordination/store-provider.ts"() {
|
|
4513
|
+
"use strict";
|
|
4514
|
+
init_fence();
|
|
4515
|
+
init_client_registry();
|
|
4516
|
+
DEFAULT_POLL_INTERVAL_MS = 50;
|
|
4517
|
+
StoreCoordinationProvider = class {
|
|
4518
|
+
#store;
|
|
4519
|
+
#pollIntervalMs;
|
|
4520
|
+
constructor(store, opts) {
|
|
4521
|
+
this.#store = store;
|
|
4522
|
+
this.#pollIntervalMs = opts?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
4523
|
+
}
|
|
4524
|
+
async setFence(vault, fence) {
|
|
4525
|
+
await saveFence(this.#store, vault, fence);
|
|
4526
|
+
}
|
|
4527
|
+
async readFence(vault) {
|
|
4528
|
+
return loadFence(this.#store, vault);
|
|
4529
|
+
}
|
|
4530
|
+
observeFence(vault, onChange) {
|
|
4531
|
+
let last = null;
|
|
4532
|
+
let busy = false;
|
|
4533
|
+
const poll = async () => {
|
|
4534
|
+
if (busy) return;
|
|
4535
|
+
busy = true;
|
|
4536
|
+
try {
|
|
4537
|
+
const fence = await loadFence(this.#store, vault);
|
|
4538
|
+
if (last === null || !fenceEqual(last, fence)) {
|
|
4539
|
+
last = fence;
|
|
4540
|
+
onChange(fence);
|
|
4541
|
+
}
|
|
4542
|
+
} catch {
|
|
4543
|
+
} finally {
|
|
4544
|
+
busy = false;
|
|
4545
|
+
}
|
|
4546
|
+
};
|
|
4547
|
+
void poll();
|
|
4548
|
+
const timer = setInterval(() => void poll(), this.#pollIntervalMs);
|
|
4549
|
+
unref(timer);
|
|
4550
|
+
return () => clearInterval(timer);
|
|
4551
|
+
}
|
|
4552
|
+
async reportPresence(vault, p) {
|
|
4553
|
+
await writeClientDoc(this.#store, vault, p.writerId, {
|
|
4554
|
+
lastSeen: p.lastSeen,
|
|
4555
|
+
quiescedAtVersion: p.quiescedAtVersion,
|
|
4556
|
+
sessionId: p.sessionId
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4559
|
+
observePresence(vault, onChange) {
|
|
4560
|
+
let last = null;
|
|
4561
|
+
let busy = false;
|
|
4562
|
+
const poll = async () => {
|
|
4563
|
+
if (busy) return;
|
|
4564
|
+
busy = true;
|
|
4565
|
+
try {
|
|
4566
|
+
const docs = await listClientDocs(this.#store, vault);
|
|
4567
|
+
const writers = docs.map(toPresence);
|
|
4568
|
+
if (last === null || !presenceListEqual(last, writers)) {
|
|
4569
|
+
last = writers;
|
|
4570
|
+
onChange(writers);
|
|
4571
|
+
}
|
|
4572
|
+
} catch {
|
|
4573
|
+
} finally {
|
|
4574
|
+
busy = false;
|
|
4575
|
+
}
|
|
4576
|
+
};
|
|
4577
|
+
void poll();
|
|
4578
|
+
const timer = setInterval(() => void poll(), this.#pollIntervalMs);
|
|
4579
|
+
unref(timer);
|
|
4580
|
+
return () => clearInterval(timer);
|
|
4581
|
+
}
|
|
4582
|
+
async reachableWriters(vault, o) {
|
|
4583
|
+
const docs = await listClientDocs(this.#store, vault);
|
|
4584
|
+
return docs.map(toPresence).filter((w) => o.now - w.lastSeen <= o.staleMs);
|
|
4585
|
+
}
|
|
4586
|
+
};
|
|
4587
|
+
}
|
|
4588
|
+
});
|
|
4589
|
+
|
|
4590
|
+
// src/coordination/index.ts
|
|
4591
|
+
var init_coordination = __esm({
|
|
4592
|
+
"src/coordination/index.ts"() {
|
|
4593
|
+
"use strict";
|
|
4594
|
+
init_types3();
|
|
4595
|
+
init_store_provider();
|
|
4596
|
+
}
|
|
4597
|
+
});
|
|
4598
|
+
|
|
4356
4599
|
// src/policy/storage.ts
|
|
4357
4600
|
async function loadVaultPolicy(store, vault) {
|
|
4358
|
-
const envelope = await store.get(vault,
|
|
4601
|
+
const envelope = await store.get(vault, META_COLLECTION4, POLICY_RECORD_ID);
|
|
4359
4602
|
if (!envelope) return void 0;
|
|
4360
4603
|
try {
|
|
4361
4604
|
const parsed = JSON.parse(envelope._data);
|
|
@@ -4373,7 +4616,7 @@ async function saveVaultPolicy(store, vault, policy) {
|
|
|
4373
4616
|
_iv: "",
|
|
4374
4617
|
_data: JSON.stringify(policy)
|
|
4375
4618
|
};
|
|
4376
|
-
await store.put(vault,
|
|
4619
|
+
await store.put(vault, META_COLLECTION4, POLICY_RECORD_ID, envelope);
|
|
4377
4620
|
}
|
|
4378
4621
|
function isVaultPolicy(x) {
|
|
4379
4622
|
if (x === null || typeof x !== "object") return false;
|
|
@@ -4381,12 +4624,12 @@ function isVaultPolicy(x) {
|
|
|
4381
4624
|
const gates = x.gates;
|
|
4382
4625
|
return gates !== null && typeof gates === "object";
|
|
4383
4626
|
}
|
|
4384
|
-
var
|
|
4627
|
+
var META_COLLECTION4, POLICY_RECORD_ID;
|
|
4385
4628
|
var init_storage5 = __esm({
|
|
4386
4629
|
"src/policy/storage.ts"() {
|
|
4387
4630
|
"use strict";
|
|
4388
4631
|
init_types();
|
|
4389
|
-
|
|
4632
|
+
META_COLLECTION4 = "_meta";
|
|
4390
4633
|
POLICY_RECORD_ID = "policy";
|
|
4391
4634
|
}
|
|
4392
4635
|
});
|
|
@@ -4541,7 +4784,7 @@ function resolveSchema(schema) {
|
|
|
4541
4784
|
};
|
|
4542
4785
|
}
|
|
4543
4786
|
var PUBLIC_ENVELOPE_FIELDS, DEFAULT_PUBLIC_ENVELOPE_SCHEMA;
|
|
4544
|
-
var
|
|
4787
|
+
var init_types4 = __esm({
|
|
4545
4788
|
"src/meta/public-envelope/types.ts"() {
|
|
4546
4789
|
"use strict";
|
|
4547
4790
|
PUBLIC_ENVELOPE_FIELDS = [
|
|
@@ -4579,7 +4822,7 @@ __export(public_envelope_exports, {
|
|
|
4579
4822
|
var init_public_envelope = __esm({
|
|
4580
4823
|
"src/meta/public-envelope/index.ts"() {
|
|
4581
4824
|
"use strict";
|
|
4582
|
-
|
|
4825
|
+
init_types4();
|
|
4583
4826
|
init_schema();
|
|
4584
4827
|
init_storage();
|
|
4585
4828
|
}
|
|
@@ -15134,108 +15377,18 @@ var init_gate = __esm({
|
|
|
15134
15377
|
}
|
|
15135
15378
|
});
|
|
15136
15379
|
|
|
15137
|
-
// src/schema-update/fence.ts
|
|
15138
|
-
async function loadFence(store, vault) {
|
|
15139
|
-
const envelope = await store.get(vault, META_COLLECTION3, FENCE_RECORD_ID);
|
|
15140
|
-
if (!envelope) return DEFAULT_FENCE;
|
|
15141
|
-
try {
|
|
15142
|
-
const parsed = JSON.parse(envelope._data);
|
|
15143
|
-
if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
|
|
15144
|
-
return parsed;
|
|
15145
|
-
} catch {
|
|
15146
|
-
return DEFAULT_FENCE;
|
|
15147
|
-
}
|
|
15148
|
-
}
|
|
15149
|
-
async function saveFence(store, vault, fence) {
|
|
15150
|
-
const envelope = {
|
|
15151
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
15152
|
-
_v: 1,
|
|
15153
|
-
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15154
|
-
_iv: "",
|
|
15155
|
-
_data: JSON.stringify(fence)
|
|
15156
|
-
};
|
|
15157
|
-
await store.put(vault, META_COLLECTION3, FENCE_RECORD_ID, envelope);
|
|
15158
|
-
}
|
|
15159
|
-
function isFenceDoc(x) {
|
|
15160
|
-
if (x === null || typeof x !== "object") return false;
|
|
15161
|
-
const o = x;
|
|
15162
|
-
return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
|
|
15163
|
-
}
|
|
15164
|
-
var FENCE_RECORD_ID, META_COLLECTION3, DEFAULT_FENCE;
|
|
15165
|
-
var init_fence = __esm({
|
|
15166
|
-
"src/schema-update/fence.ts"() {
|
|
15167
|
-
"use strict";
|
|
15168
|
-
init_types();
|
|
15169
|
-
FENCE_RECORD_ID = "schema-fence";
|
|
15170
|
-
META_COLLECTION3 = "_meta";
|
|
15171
|
-
DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
|
|
15172
|
-
}
|
|
15173
|
-
});
|
|
15174
|
-
|
|
15175
|
-
// src/schema-update/client-registry.ts
|
|
15176
|
-
async function writeClientDoc(store, vault, clientId, doc) {
|
|
15177
|
-
const envelope = {
|
|
15178
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
15179
|
-
_v: 1,
|
|
15180
|
-
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15181
|
-
_iv: "",
|
|
15182
|
-
_data: JSON.stringify({ clientId, ...doc })
|
|
15183
|
-
};
|
|
15184
|
-
await store.put(vault, META_COLLECTION4, `${CLIENT_PREFIX}${clientId}`, envelope);
|
|
15185
|
-
}
|
|
15186
|
-
async function listClientDocs(store, vault) {
|
|
15187
|
-
const ids = await store.list(vault, META_COLLECTION4);
|
|
15188
|
-
const out = [];
|
|
15189
|
-
for (const id of ids) {
|
|
15190
|
-
if (!id.startsWith(CLIENT_PREFIX)) continue;
|
|
15191
|
-
const env = await store.get(vault, META_COLLECTION4, id);
|
|
15192
|
-
if (!env) continue;
|
|
15193
|
-
try {
|
|
15194
|
-
const parsed = JSON.parse(env._data);
|
|
15195
|
-
if (isClientDoc(parsed)) out.push(parsed);
|
|
15196
|
-
} catch {
|
|
15197
|
-
}
|
|
15198
|
-
}
|
|
15199
|
-
return out;
|
|
15200
|
-
}
|
|
15201
|
-
async function activeQuiesced(store, vault, opts) {
|
|
15202
|
-
const docs = await listClientDocs(store, vault);
|
|
15203
|
-
const active = docs.filter(
|
|
15204
|
-
(d) => d.lastSeen >= opts.now - opts.staleMs && d.clientId !== opts.excludeClientId
|
|
15205
|
-
);
|
|
15206
|
-
return active.every((d) => d.quiescedAtVersion === opts.generation);
|
|
15207
|
-
}
|
|
15208
|
-
function isClientDoc(x) {
|
|
15209
|
-
if (x === null || typeof x !== "object") return false;
|
|
15210
|
-
const o = x;
|
|
15211
|
-
return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number");
|
|
15212
|
-
}
|
|
15213
|
-
var META_COLLECTION4, CLIENT_PREFIX;
|
|
15214
|
-
var init_client_registry = __esm({
|
|
15215
|
-
"src/schema-update/client-registry.ts"() {
|
|
15216
|
-
"use strict";
|
|
15217
|
-
init_types();
|
|
15218
|
-
META_COLLECTION4 = "_meta";
|
|
15219
|
-
CLIENT_PREFIX = "schema-fence:client:";
|
|
15220
|
-
}
|
|
15221
|
-
});
|
|
15222
|
-
|
|
15223
15380
|
// src/schema-update/fence-controller.ts
|
|
15224
|
-
function delay(ms) {
|
|
15225
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15226
|
-
}
|
|
15227
15381
|
var SchemaFenceController;
|
|
15228
15382
|
var init_fence_controller = __esm({
|
|
15229
15383
|
"src/schema-update/fence-controller.ts"() {
|
|
15230
15384
|
"use strict";
|
|
15231
|
-
init_fence();
|
|
15232
15385
|
init_errors();
|
|
15233
|
-
|
|
15386
|
+
init_coordination();
|
|
15234
15387
|
SchemaFenceController = class {
|
|
15235
|
-
#
|
|
15388
|
+
#coordination;
|
|
15236
15389
|
#vault;
|
|
15237
15390
|
#onFlush;
|
|
15238
|
-
#
|
|
15391
|
+
#writerId;
|
|
15239
15392
|
#now;
|
|
15240
15393
|
#staleMs;
|
|
15241
15394
|
#quiesceTimeoutMs;
|
|
@@ -15243,10 +15396,10 @@ var init_fence_controller = __esm({
|
|
|
15243
15396
|
#snapshot = 0;
|
|
15244
15397
|
#pending = /* @__PURE__ */ new Map();
|
|
15245
15398
|
constructor(opts) {
|
|
15246
|
-
this.#
|
|
15399
|
+
this.#coordination = opts.coordination;
|
|
15247
15400
|
this.#vault = opts.vault;
|
|
15248
15401
|
this.#onFlush = opts.onFlush;
|
|
15249
|
-
this.#
|
|
15402
|
+
this.#writerId = opts.clientId ?? "migrator";
|
|
15250
15403
|
this.#now = opts.now ?? (() => Date.now());
|
|
15251
15404
|
this.#staleMs = opts.staleMs ?? 3e4;
|
|
15252
15405
|
this.#quiesceTimeoutMs = opts.quiesceTimeoutMs ?? 6e4;
|
|
@@ -15255,7 +15408,7 @@ var init_fence_controller = __esm({
|
|
|
15255
15408
|
}
|
|
15256
15409
|
/** Capture the generation snapshot at vault-open. */
|
|
15257
15410
|
async init() {
|
|
15258
|
-
this.#snapshot = (await
|
|
15411
|
+
this.#snapshot = (await this.#coordination.readFence(this.#vault)).currentSchemaVersion;
|
|
15259
15412
|
}
|
|
15260
15413
|
/** Record a per-collection pending cutover (from a registration `cutover` decision). */
|
|
15261
15414
|
registerPendingCutover(collection, transform) {
|
|
@@ -15263,7 +15416,7 @@ var init_fence_controller = __esm({
|
|
|
15263
15416
|
}
|
|
15264
15417
|
/** Write-path gate. Throws when behind, fenced, or this collection is cutover-pending. */
|
|
15265
15418
|
async assertWritable(collection) {
|
|
15266
|
-
const fence = await
|
|
15419
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
15267
15420
|
if (fence.currentSchemaVersion > this.#snapshot) {
|
|
15268
15421
|
throw new MigrationRequiredError(
|
|
15269
15422
|
`Vault "${this.#vault}" advanced to schema generation ${fence.currentSchemaVersion} (this client opened at ${this.#snapshot}). Reload to continue.`
|
|
@@ -15282,49 +15435,49 @@ var init_fence_controller = __esm({
|
|
|
15282
15435
|
* Admin trigger. Drain → wait for the active set to quiesce (or time out)
|
|
15283
15436
|
* → migrate each pending transform → bump → complete → normal. The
|
|
15284
15437
|
* migrator excludes itself from the barrier (it drained synchronously
|
|
15285
|
-
*
|
|
15286
|
-
* production falls back to a short real delay.
|
|
15438
|
+
* inside {@link runDrainBarrier}). `onPoll` (tests) advances other clients
|
|
15439
|
+
* between barrier checks; production falls back to a short real delay.
|
|
15287
15440
|
*/
|
|
15288
15441
|
async runCutover(run, opts) {
|
|
15289
15442
|
if (this.#pending.size === 0) return { migrated: 0 };
|
|
15290
|
-
const base = await
|
|
15443
|
+
const base = await this.#coordination.readFence(this.#vault);
|
|
15291
15444
|
const generation = base.currentSchemaVersion;
|
|
15292
|
-
|
|
15293
|
-
await this.#onFlush();
|
|
15294
|
-
const deadline = this.#now() + this.#quiesceTimeoutMs;
|
|
15295
|
-
while (!await activeQuiesced(this.#store, this.#vault, {
|
|
15296
|
-
generation,
|
|
15297
|
-
now: this.#now(),
|
|
15298
|
-
staleMs: this.#staleMs,
|
|
15299
|
-
excludeClientId: this.#clientId
|
|
15300
|
-
})) {
|
|
15301
|
-
if (this.#now() >= deadline) {
|
|
15302
|
-
throw new QuiesceTimeoutError(
|
|
15303
|
-
`Cutover on "${this.#vault}" timed out waiting for clients to quiesce at generation ${generation}.`
|
|
15304
|
-
);
|
|
15305
|
-
}
|
|
15306
|
-
await (opts?.onPoll ? opts.onPoll() : delay(50));
|
|
15307
|
-
}
|
|
15308
|
-
await this.#setState(generation, "migrating");
|
|
15445
|
+
this.#emit({ currentSchemaVersion: generation, fenceState: "draining" });
|
|
15309
15446
|
let migrated = 0;
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15447
|
+
await runDrainBarrier(
|
|
15448
|
+
this.#coordination,
|
|
15449
|
+
{
|
|
15450
|
+
vault: this.#vault,
|
|
15451
|
+
generation,
|
|
15452
|
+
writerId: this.#writerId,
|
|
15453
|
+
onFlush: this.#onFlush,
|
|
15454
|
+
staleMs: this.#staleMs,
|
|
15455
|
+
quiesceTimeoutMs: this.#quiesceTimeoutMs,
|
|
15456
|
+
now: this.#now,
|
|
15457
|
+
...opts?.onPoll ? { onPoll: opts.onPoll } : {}
|
|
15458
|
+
},
|
|
15459
|
+
async () => {
|
|
15460
|
+
await this.#setState(generation, "migrating");
|
|
15461
|
+
for (const [collection, transform] of this.#pending) {
|
|
15462
|
+
await run(collection, transform);
|
|
15463
|
+
migrated++;
|
|
15464
|
+
}
|
|
15465
|
+
const nextVersion = generation + 1;
|
|
15466
|
+
await this.#setState(nextVersion, "complete");
|
|
15467
|
+
this.#pending.clear();
|
|
15468
|
+
await this.#setState(nextVersion, "normal");
|
|
15469
|
+
this.#snapshot = nextVersion;
|
|
15470
|
+
}
|
|
15471
|
+
);
|
|
15319
15472
|
return { migrated };
|
|
15320
15473
|
}
|
|
15321
15474
|
/** Recover a stuck drain: reset fenceState to normal at the current version (no bump). */
|
|
15322
15475
|
async abort() {
|
|
15323
|
-
const fence = await
|
|
15476
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
15324
15477
|
await this.#setState(fence.currentSchemaVersion, "normal");
|
|
15325
15478
|
}
|
|
15326
15479
|
async #setState(currentSchemaVersion, fenceState) {
|
|
15327
|
-
await
|
|
15480
|
+
await this.#coordination.setFence(this.#vault, { currentSchemaVersion, fenceState });
|
|
15328
15481
|
this.#emit({ currentSchemaVersion, fenceState });
|
|
15329
15482
|
}
|
|
15330
15483
|
};
|
|
@@ -15336,12 +15489,11 @@ var FenceWatcher;
|
|
|
15336
15489
|
var init_fence_watcher = __esm({
|
|
15337
15490
|
"src/schema-update/fence-watcher.ts"() {
|
|
15338
15491
|
"use strict";
|
|
15339
|
-
init_fence();
|
|
15340
|
-
init_client_registry();
|
|
15341
15492
|
FenceWatcher = class {
|
|
15342
|
-
#
|
|
15493
|
+
#coordination;
|
|
15343
15494
|
#vault;
|
|
15344
|
-
#
|
|
15495
|
+
#writerId;
|
|
15496
|
+
#sessionId;
|
|
15345
15497
|
#onFlush;
|
|
15346
15498
|
#now;
|
|
15347
15499
|
#emit;
|
|
@@ -15349,9 +15501,10 @@ var init_fence_watcher = __esm({
|
|
|
15349
15501
|
#quiescedAtVersion = null;
|
|
15350
15502
|
#timer;
|
|
15351
15503
|
constructor(opts) {
|
|
15352
|
-
this.#
|
|
15504
|
+
this.#coordination = opts.coordination;
|
|
15353
15505
|
this.#vault = opts.vault;
|
|
15354
|
-
this.#
|
|
15506
|
+
this.#writerId = opts.clientId;
|
|
15507
|
+
this.#sessionId = opts.sessionId ?? opts.clientId;
|
|
15355
15508
|
this.#onFlush = opts.onFlush;
|
|
15356
15509
|
this.#now = opts.now ?? (() => Date.now());
|
|
15357
15510
|
this.#emit = opts.emit ?? (() => {
|
|
@@ -15359,14 +15512,16 @@ var init_fence_watcher = __esm({
|
|
|
15359
15512
|
}
|
|
15360
15513
|
/** Publish liveness (and the current ack) without changing quiesce state. */
|
|
15361
15514
|
async beat() {
|
|
15362
|
-
await
|
|
15515
|
+
await this.#coordination.reportPresence(this.#vault, {
|
|
15516
|
+
writerId: this.#writerId,
|
|
15517
|
+
sessionId: this.#sessionId,
|
|
15363
15518
|
lastSeen: this.#now(),
|
|
15364
15519
|
quiescedAtVersion: this.#quiescedAtVersion
|
|
15365
15520
|
});
|
|
15366
15521
|
}
|
|
15367
15522
|
/** Poll the fence; quiesce on draining; emit on transitions. */
|
|
15368
15523
|
async check() {
|
|
15369
|
-
const fence = await
|
|
15524
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
15370
15525
|
if (fence.fenceState !== this.#lastState) {
|
|
15371
15526
|
this.#lastState = fence.fenceState;
|
|
15372
15527
|
this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
|
|
@@ -16678,10 +16833,11 @@ var init_vault = __esm({
|
|
|
16678
16833
|
this.keyring = opts.keyring;
|
|
16679
16834
|
this.encrypted = opts.encrypted;
|
|
16680
16835
|
this.schemaFence = new SchemaFenceController({
|
|
16681
|
-
|
|
16836
|
+
coordination: this.noydb.coordination,
|
|
16682
16837
|
vault: this.name,
|
|
16683
16838
|
onFlush: () => this.noydb._writeQueueTracker.onFlush(),
|
|
16684
16839
|
clientId: this.noydb._clientId,
|
|
16840
|
+
sessionId: this.noydb._sessionId,
|
|
16685
16841
|
emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
|
|
16686
16842
|
});
|
|
16687
16843
|
this.emitter = opts.emitter;
|
|
@@ -17077,9 +17233,10 @@ var init_vault = __esm({
|
|
|
17077
17233
|
if (this.#fenceCoordinationStarted) return;
|
|
17078
17234
|
this.#fenceCoordinationStarted = true;
|
|
17079
17235
|
this.#fenceWatcher = new FenceWatcher({
|
|
17080
|
-
|
|
17236
|
+
coordination: this.noydb.coordination,
|
|
17081
17237
|
vault: this.name,
|
|
17082
17238
|
clientId: this.noydb._clientId,
|
|
17239
|
+
sessionId: this.noydb._sessionId,
|
|
17083
17240
|
onFlush: () => this.noydb._writeQueueTracker.onFlush(),
|
|
17084
17241
|
emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
|
|
17085
17242
|
});
|
|
@@ -21043,6 +21200,7 @@ var init_noydb = __esm({
|
|
|
21043
21200
|
init_recovery();
|
|
21044
21201
|
init_managed_passphrase();
|
|
21045
21202
|
init_ulid();
|
|
21203
|
+
init_coordination();
|
|
21046
21204
|
init_errors2();
|
|
21047
21205
|
init_auth_introspection();
|
|
21048
21206
|
init_public_envelope();
|
|
@@ -21086,6 +21244,10 @@ var init_noydb = __esm({
|
|
|
21086
21244
|
writeHooks = new WriteHookRegistry();
|
|
21087
21245
|
subsystemBus = new SubsystemBus();
|
|
21088
21246
|
clientId = generateULID();
|
|
21247
|
+
/** Session that owns this instance's writers (one user's writers across vaults). */
|
|
21248
|
+
sessionId;
|
|
21249
|
+
/** Drain-barrier coordination transport for the schema fence (#469). */
|
|
21250
|
+
coordinationProvider;
|
|
21089
21251
|
vaultCache = /* @__PURE__ */ new Map();
|
|
21090
21252
|
keyringCache = /* @__PURE__ */ new Map();
|
|
21091
21253
|
syncEngines = /* @__PURE__ */ new Map();
|
|
@@ -21160,6 +21322,8 @@ var init_noydb = __esm({
|
|
|
21160
21322
|
"[noydb] debugPlaintext is ON \u2014 records are stored UNENCRYPTED and laid out for native store inspection. NEVER use this for production or client data."
|
|
21161
21323
|
);
|
|
21162
21324
|
}
|
|
21325
|
+
this.sessionId = options.sessionId ?? generateULID();
|
|
21326
|
+
this.coordinationProvider = options.coordinationStrategy ?? new StoreCoordinationProvider(options.store);
|
|
21163
21327
|
this.txStrategy = options.txStrategy ?? NO_TX;
|
|
21164
21328
|
this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
|
|
21165
21329
|
this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
|
|
@@ -22213,6 +22377,18 @@ var init_noydb = __esm({
|
|
|
22213
22377
|
get _clientId() {
|
|
22214
22378
|
return this.clientId;
|
|
22215
22379
|
}
|
|
22380
|
+
/** @internal Session that owns this instance's writers (#469). */
|
|
22381
|
+
get _sessionId() {
|
|
22382
|
+
return this.sessionId;
|
|
22383
|
+
}
|
|
22384
|
+
/**
|
|
22385
|
+
* @internal Drain-barrier coordination transport for the schema fence (#469).
|
|
22386
|
+
* The default store-backed provider reproduces today's fence behavior; a
|
|
22387
|
+
* `by-*` real-time transport is injected via `coordinationStrategy`.
|
|
22388
|
+
*/
|
|
22389
|
+
get coordination() {
|
|
22390
|
+
return this.coordinationProvider;
|
|
22391
|
+
}
|
|
22216
22392
|
/**
|
|
22217
22393
|
* Soft-lock a single vault: clear its in-memory keyring, DEKs, vault
|
|
22218
22394
|
* instance, sync engine, policy enforcer, and active-tier entry —
|