@cello-protocol/daemon 0.0.166 → 0.0.168
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/daemon.d.ts.map +1 -1
- package/dist/daemon.js +52 -5
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-session-suspects.d.ts +56 -0
- package/dist/delivery-session-suspects.d.ts.map +1 -0
- package/dist/delivery-session-suspects.js +89 -0
- package/dist/delivery-session-suspects.js.map +1 -0
- package/dist/delivery-sweep-bound.d.ts +79 -0
- package/dist/delivery-sweep-bound.d.ts.map +1 -0
- package/dist/delivery-sweep-bound.js +109 -0
- package/dist/delivery-sweep-bound.js.map +1 -0
- package/dist/document-control-notifier.d.ts +17 -0
- package/dist/document-control-notifier.d.ts.map +1 -1
- package/dist/document-control-notifier.js +40 -1
- package/dist/document-control-notifier.js.map +1 -1
- package/dist/document-delivery-transport.d.ts +2 -0
- package/dist/document-delivery-transport.d.ts.map +1 -1
- package/dist/document-delivery-transport.js +78 -3
- package/dist/document-delivery-transport.js.map +1 -1
- package/dist/document-delivery.d.ts +30 -4
- package/dist/document-delivery.d.ts.map +1 -1
- package/dist/document-delivery.js +294 -1
- package/dist/document-delivery.js.map +1 -1
- package/dist/document-handlers.d.ts.map +1 -1
- package/dist/document-handlers.js +209 -60
- package/dist/document-handlers.js.map +1 -1
- package/dist/document-layer.d.ts.map +1 -1
- package/dist/document-layer.js +16 -1
- package/dist/document-layer.js.map +1 -1
- package/dist/document-lifecycle.d.ts.map +1 -1
- package/dist/document-lifecycle.js +10 -3
- package/dist/document-lifecycle.js.map +1 -1
- package/dist/document-store.d.ts +90 -0
- package/dist/document-store.d.ts.map +1 -1
- package/dist/document-store.js +311 -0
- package/dist/document-store.js.map +1 -1
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +14 -2
- package/dist/session-node-manager.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAMrB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAmC,KAAK,UAAU,EAAsB,MAAM,iBAAiB,CAAC;AAEvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAO/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAiB7G,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAsB,MAAM,2BAA2B,CAAC;AAS5G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAMrB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAmC,KAAK,UAAU,EAAsB,MAAM,iBAAiB,CAAC;AAEvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAO/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAiB7G,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAsB,MAAM,2BAA2B,CAAC;AAS5G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AA8BnF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWlD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,oBAAoB,CAAC;IAClC;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,CAAC;IAC5C;;;;OAIG;IACH,oBAAoB,IAAI,kBAAkB,CAAC;IAC3C;;;OAGG;IACH,iBAAiB,IAAI,eAAe,CAAC;IACrC;;OAEG;IACH,eAAe,IAAI,YAAY,CAAC;IAChC;;;;;;;;OAQG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACxC;AAYD,qBAAa,4BAA6B,YAAW,mBAAmB;IAChE,UAAU,CAAC,MAAM,EAAE,iBAAiB;CA8B3C;AAID,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAS7E"}
|
package/dist/daemon.js
CHANGED
|
@@ -72,6 +72,7 @@ import { wireContentHash } from "./wire-content-hash.js";
|
|
|
72
72
|
import { DocumentPublish } from "./document-publish.js";
|
|
73
73
|
import { createDocumentDeliveryTransport } from "./document-delivery-transport.js";
|
|
74
74
|
import { DocumentDelivery } from "./document-delivery.js";
|
|
75
|
+
import { sweepAgentEvicting } from "./delivery-sweep-bound.js";
|
|
75
76
|
import { encodeDocumentUpdateEnvelope, DOCUMENT_UPDATE_ENCODING_V1 } from "@cello-protocol/protocol-types";
|
|
76
77
|
import { createSealFlows } from "./seal-flows.js";
|
|
77
78
|
import { registerCloseSessionHandler } from "./close-session-handler.js";
|
|
@@ -3610,7 +3611,18 @@ async function startDaemonHoldingLock(config, singletonLock) {
|
|
|
3610
3611
|
const existing = documentDeliveryWorkers.get(agentName);
|
|
3611
3612
|
if (existing)
|
|
3612
3613
|
return existing;
|
|
3613
|
-
const worker = new DocumentDelivery(documentLayer.store, documentTransportFor(agentName), logger
|
|
3614
|
+
const worker = new DocumentDelivery(documentLayer.store, documentTransportFor(agentName), logger,
|
|
3615
|
+
// DOD-MP-CONTROL-DURABLE-1 — control frames derive their recipients the way the NOTIFIER
|
|
3616
|
+
// does, not the way envelopes do. `holdersFor` returns null for a document with no stored
|
|
3617
|
+
// genesis proposal; `controlHolders` has an explicit legacy branch for it. Deriving the two
|
|
3618
|
+
// halves differently turned a seeded row into a permanent no-op.
|
|
3619
|
+
(documentId) => {
|
|
3620
|
+
const ownerAgentId = documentOwnerKeyFor(agentName);
|
|
3621
|
+
if (ownerAgentId === null) {
|
|
3622
|
+
return { ok: false, reason: "document_owner_key_unavailable" };
|
|
3623
|
+
}
|
|
3624
|
+
return documentLayer.controlHolders(ownerAgentId, documentId);
|
|
3625
|
+
});
|
|
3614
3626
|
documentDeliveryWorkers.set(agentName, worker);
|
|
3615
3627
|
return worker;
|
|
3616
3628
|
};
|
|
@@ -3678,6 +3690,15 @@ async function startDaemonHoldingLock(config, singletonLock) {
|
|
|
3678
3690
|
// Floored, so a misread env cannot turn the sweep into a busy loop against the directory.
|
|
3679
3691
|
const tickOverride = Number(process.env["CELLO_DOCUMENT_DELIVERY_TICK_MS"]);
|
|
3680
3692
|
const DOCUMENT_DELIVERY_TICK_MS = Number.isFinite(tickOverride) && tickOverride >= 250 ? tickOverride : 60_000;
|
|
3693
|
+
// DOD-MP-SWEEP-ALIVE-1 — how long ONE agent's pass may run before the sweep stops waiting for
|
|
3694
|
+
// it. Generous relative to real work (the ack-grace budget for a whole pass is 30s) and finite,
|
|
3695
|
+
// which is the only property that matters: the defect is an unbounded wait, not a slow one.
|
|
3696
|
+
// Generous relative to what a HEALTHY pass can legitimately spend: the discovery lookup is
|
|
3697
|
+
// bounded at 10s per (document, holder), the whole-pass ack grace is 30s, and only the dial is
|
|
3698
|
+
// unbounded. Six pairs against a slow directory is already ~90s, so a 120s bound would warn on
|
|
3699
|
+
// the normal case — and a signal that fires when nothing is wrong teaches an operator to ignore
|
|
3700
|
+
// the one that matters. Scales with the tick so the fast-tick test path does not sit out minutes.
|
|
3701
|
+
const DOCUMENT_DELIVERY_PASS_TIMEOUT_MS = Math.max(180_000, DOCUMENT_DELIVERY_TICK_MS * 3);
|
|
3681
3702
|
let documentDeliveryRunning = false;
|
|
3682
3703
|
let documentDeliveryStopping = false;
|
|
3683
3704
|
let documentDeliveryInFlight = null;
|
|
@@ -3691,6 +3712,7 @@ async function startDaemonHoldingLock(config, singletonLock) {
|
|
|
3691
3712
|
documentDeliveryInFlight = (async () => {
|
|
3692
3713
|
try {
|
|
3693
3714
|
let agentsSwept = 0;
|
|
3715
|
+
let stuck = 0;
|
|
3694
3716
|
let attempted = 0;
|
|
3695
3717
|
let delivered = 0;
|
|
3696
3718
|
let failed = 0;
|
|
@@ -3706,23 +3728,48 @@ async function startDaemonHoldingLock(config, singletonLock) {
|
|
|
3706
3728
|
// and leaves a fully synced document invisible with no error on any path.
|
|
3707
3729
|
if (ownerAgentId === null)
|
|
3708
3730
|
continue;
|
|
3709
|
-
|
|
3731
|
+
// COUNTED AFTER THE PASS, not before — an agent whose pass never finished was not swept,
|
|
3732
|
+
// and saying it was is what made the stall indistinguishable from an idle daemon.
|
|
3710
3733
|
// FANOUT-1: targets are the DERIVED holders minus ourselves — never per-sender
|
|
3711
3734
|
// config, never the genesis peer column (§7-1's silent-divergence hazard).
|
|
3712
3735
|
const holdersFor = (documentId) => {
|
|
3713
3736
|
const holders = documentLayer.holdersFor(ownerAgentId, documentId);
|
|
3714
3737
|
return holders === null ? null : holders.filter((h) => h !== ownerAgentId);
|
|
3715
3738
|
};
|
|
3716
|
-
|
|
3717
|
-
|
|
3739
|
+
// DOD-MP-SWEEP-ALIVE-1 — BOUNDED. The `finally` below releases the overlap guard only
|
|
3740
|
+
// when this body settles, so an await that never settles ends document delivery for the
|
|
3741
|
+
// life of the process, silently: the interval keeps firing, returns at the guard, and
|
|
3742
|
+
// logs nothing. Observed live 2026-08-13. One wedged agent now degrades alone and loudly
|
|
3743
|
+
// instead of taking every other agent's documents down with it.
|
|
3744
|
+
const bounded = await sweepAgentEvicting({
|
|
3745
|
+
logger,
|
|
3746
|
+
timeoutMs: DOCUMENT_DELIVERY_PASS_TIMEOUT_MS,
|
|
3747
|
+
agentName,
|
|
3748
|
+
// Evicting the wedged worker is what makes the recovery real: `DocumentDelivery.tick`
|
|
3749
|
+
// caches its pass and would otherwise hand back the same hung promise forever, so the
|
|
3750
|
+
// agent would never deliver again AND every later pass would pay the full bound
|
|
3751
|
+
// waiting for it — a 2x sweep-interval regression for every healthy agent.
|
|
3752
|
+
workers: documentDeliveryWorkers,
|
|
3753
|
+
run: () => documentDeliveryFor(agentName).tick(ownerAgentId, holdersFor, Date.now(), {
|
|
3754
|
+
senderAgentId: ownerAgentId,
|
|
3755
|
+
}),
|
|
3718
3756
|
});
|
|
3757
|
+
if (!bounded.completed) {
|
|
3758
|
+
stuck += 1;
|
|
3759
|
+
continue;
|
|
3760
|
+
}
|
|
3761
|
+
agentsSwept++;
|
|
3762
|
+
const result = bounded.value;
|
|
3719
3763
|
attempted += result.attempted;
|
|
3720
3764
|
delivered += result.delivered;
|
|
3721
3765
|
failed += result.failed;
|
|
3722
3766
|
}
|
|
3723
3767
|
// H3: a sweep that delivers nothing was byte-for-byte identical to a healthy idle one, which
|
|
3724
3768
|
// is what made every scoping bug above invisible. One line per tick, always.
|
|
3725
|
-
|
|
3769
|
+
// `stuck` IS PART OF THE LINE. Counting a wedged agent as swept reported `agents: 3,
|
|
3770
|
+
// attempted: 0` — byte-for-byte a healthy idle sweep, which is the exact shape the comment
|
|
3771
|
+
// below exists to prevent, on the one occasion it matters most.
|
|
3772
|
+
logger.debug("document.delivery.sweep", { agents: agentsSwept, stuck, attempted, delivered, failed });
|
|
3726
3773
|
if (agentsSwept === 0 && documentLayer.store.anyDocumentExists()) {
|
|
3727
3774
|
logger.warn("document.delivery.sweep_empty", {
|
|
3728
3775
|
reason: "documents exist but no agent was swept — nothing will ever be delivered",
|