@agentunion/fastaun 0.5.19 → 0.5.20
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/CHANGELOG.md +129 -78
- package/_packed_docs/CHANGELOG.md +129 -78
- package/_packed_docs/INDEX.md +201 -195
- package/_packed_docs/KITE_DOCS_GUIDE.md +93 -90
- package/_packed_docs/agent.md/SCHEMA.md +7 -7
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +11 -11
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1072 -1072
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +676 -676
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +8 -12
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +443 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.0.md +161 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +658 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2113.0.md +233 -0
- package/_packed_docs/protocol/agent.md/SCHEMA.md +1 -1
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +1 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +67 -63
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +35 -8
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +3 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +258 -254
- package/_packed_docs/sdk/09-message-rpc-manual.md +7 -4
- package/_packed_docs/sdk/09-storage-rpc-manual.md +18 -26
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +61 -52
- package/_packed_docs/sdk/INDEX.md +92 -80
- package/_packed_docs/sdk/Ownership-SDK/345/256/236/347/216/260/346/214/207/345/215/227.md +169 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/227.md +349 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +922 -0
- package/_packed_docs/sdk/Ownership-SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +270 -0
- package/_packed_docs/sdk/Ownership2.1-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +300 -0
- package/_packed_docs/sdk/Ownership2.1-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +382 -0
- package/_packed_docs/sdk/Ownership2.1-TDD/345/210/206/351/230/266/346/256/265/345/256/236/346/226/275/350/256/241/345/210/222.md +708 -0
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +476 -0
- package/_packed_docs/sdk/Ownership/347/256/241/347/220/206/344/270/223/351/242/230.md +559 -0
- package/_packed_docs/sdk/ProtectedHeaders/347/224/250/346/263/225/344/270/223/351/242/230.md +299 -0
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +173 -0
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +211 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/345/256/236/347/216/260/347/247/273/346/244/215/346/214/207/345/215/227.md +331 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +207 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/344/273/243/347/240/201/345/256/241/346/237/245/346/212/245/345/221/212.md +252 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/345/256/236/346/226/275/350/256/241/345/210/222.md +156 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/346/226/271/346/241/210.md +273 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/350/257/246/347/273/206/350/256/276/350/256/241.md +211 -0
- package/dist/agent-md-schema.d.ts +13 -1
- package/dist/agent-md-schema.js +61 -33
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +8 -1
- package/dist/agent-md.js +243 -119
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +29 -0
- package/dist/aid-store.js +179 -34
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.js +18 -13
- package/dist/aid.js.map +1 -1
- package/dist/auth.js +74 -2
- package/dist/auth.js.map +1 -1
- package/dist/cert-utils.d.ts +43 -1
- package/dist/cert-utils.js +144 -56
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +9 -0
- package/dist/client/delivery.js +179 -11
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +1 -0
- package/dist/client/rpc-pipeline.js +125 -82
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.js +95 -89
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.js +48 -19
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +5 -3
- package/dist/events.js +25 -8
- package/dist/events.js.map +1 -1
- package/dist/facades.js +5 -5
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +1 -1
- package/dist/keystore/aid-db.js +11 -2
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/index.d.ts +1 -1
- package/dist/keystore/local-token-store.d.ts +1 -1
- package/dist/keystore/local-token-store.js +2 -2
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/org-protocol.js +77 -13
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.d.ts +26 -8
- package/dist/ownership-v21.js +147 -70
- package/dist/ownership-v21.js.map +1 -1
- package/dist/ownership-workflow.d.ts +5 -0
- package/dist/ownership-workflow.js +366 -56
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +2 -1
- package/dist/tools/cross-sdk-agent.js +109 -6
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.js +10 -0
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client/v2-e2ee.js
CHANGED
|
@@ -113,13 +113,13 @@ function deduplicateForwardPageMessages(value, afterSeq) {
|
|
|
113
113
|
function contiguousPullSeq(afterSeq, seqs, proof) {
|
|
114
114
|
const pulledMax = seqs.length > 0 ? Math.max(...seqs) : 0;
|
|
115
115
|
const serverProof = safeNonNegativeSeq(proof);
|
|
116
|
-
return Math.max(afterSeq, pulledMax, serverProof ?? 0);
|
|
116
|
+
return Math.max(afterSeq, pulledMax, pulledMax > 0 ? 0 : serverProof ?? 0);
|
|
117
117
|
}
|
|
118
118
|
function shouldContinueForwardPage({ rawCount, nextAfterSeq, nextAfter, limit, hasMoreField, hasMore, serverHead, observedUpper, pendingAckSeq, }) {
|
|
119
119
|
// 无新 seq 或游标未前进时必须停止,避免错误元数据造成循环。
|
|
120
120
|
if (rawCount <= 0 || nextAfter <= nextAfterSeq)
|
|
121
121
|
return false;
|
|
122
|
-
if (hasMore || serverHead > nextAfter || observedUpper > nextAfter
|
|
122
|
+
if (hasMore || serverHead > nextAfter || observedUpper > nextAfter)
|
|
123
123
|
return true;
|
|
124
124
|
// 仅旧服务缺失 has_more 时,以满页保留兼容续拉。
|
|
125
125
|
return !hasMoreField && limit > 0 && rawCount >= limit;
|
|
@@ -917,10 +917,14 @@ export class V2E2EECoordinator {
|
|
|
917
917
|
});
|
|
918
918
|
}
|
|
919
919
|
}
|
|
920
|
+
const targetDeviceId = String(opts.deviceId ?? '').trim();
|
|
921
|
+
if (useCache && targetDeviceId && !peerDevices.some((dev) => String(dev.device_id ?? '').trim() === targetDeviceId)) {
|
|
922
|
+
this.deleteBootstrapCacheEntry(to);
|
|
923
|
+
return this.buildV2P2PEnvelope({ ...opts, useCache: false });
|
|
924
|
+
}
|
|
920
925
|
if (peerDevices.length === 0) {
|
|
921
926
|
throw new E2EEError(`V2 bootstrap: no devices found for ${to}`);
|
|
922
927
|
}
|
|
923
|
-
const targetDeviceId = String(opts.deviceId ?? '').trim();
|
|
924
928
|
if (targetDeviceId && !peerDevices.some((dev) => String(dev.device_id ?? '').trim() === targetDeviceId)) {
|
|
925
929
|
throw new E2EEError(`V2 bootstrap: target device ${targetDeviceId} not found for ${to}`);
|
|
926
930
|
}
|
|
@@ -1007,6 +1011,10 @@ export class V2E2EECoordinator {
|
|
|
1007
1011
|
targetSet = this.cloneP2PTargetSet(targetSet);
|
|
1008
1012
|
}
|
|
1009
1013
|
if (targetSet.targets.length === 0) {
|
|
1014
|
+
if (useCache && targetDeviceId) {
|
|
1015
|
+
this.deleteBootstrapCacheEntry(to);
|
|
1016
|
+
return this.buildV2P2PEnvelope({ ...opts, useCache: false });
|
|
1017
|
+
}
|
|
1010
1018
|
throw new E2EEError(`V2 bootstrap: no usable devices found for ${to}`);
|
|
1011
1019
|
}
|
|
1012
1020
|
if (targetDeviceId) {
|
|
@@ -1020,6 +1028,10 @@ export class V2E2EECoordinator {
|
|
|
1020
1028
|
return isPeerTarget || target.role === 'self_sync';
|
|
1021
1029
|
});
|
|
1022
1030
|
if (!peerTargetFound) {
|
|
1031
|
+
if (useCache) {
|
|
1032
|
+
this.deleteBootstrapCacheEntry(to);
|
|
1033
|
+
return this.buildV2P2PEnvelope({ ...opts, useCache: false });
|
|
1034
|
+
}
|
|
1023
1035
|
throw new E2EEError(`V2 bootstrap: target device ${targetDeviceId} not found for ${to}`);
|
|
1024
1036
|
}
|
|
1025
1037
|
}
|
|
@@ -1361,10 +1373,9 @@ export class V2E2EECoordinator {
|
|
|
1361
1373
|
const maxPages = Math.max(1, Math.min(100, Math.trunc(Number(opts?.maxPages ?? 100) || 100)));
|
|
1362
1374
|
let pipelineRunning = false;
|
|
1363
1375
|
let pipelineError = null;
|
|
1364
|
-
|
|
1376
|
+
let pipelineQueue = new V2PullPageQueue(V2_PULL_PIPELINE_QUEUE_CAPACITY);
|
|
1365
1377
|
let pipelineProducer = null;
|
|
1366
1378
|
let pipelineStopped = false;
|
|
1367
|
-
const pipelineResume = { current: null };
|
|
1368
1379
|
const startPipeline = (startAfterSeq, startVolatileCursor) => {
|
|
1369
1380
|
if (pipelineRunning || pageCount >= maxPages || limit < V2_PULL_MAX_PAGE_LIMIT)
|
|
1370
1381
|
return;
|
|
@@ -1375,30 +1386,31 @@ export class V2E2EECoordinator {
|
|
|
1375
1386
|
for (let produced = pageCount; produced < maxPages; produced += 1) {
|
|
1376
1387
|
if (pipelineStopped)
|
|
1377
1388
|
break;
|
|
1389
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
1378
1390
|
const requestedVolatileCursor = producerVolatileCursor;
|
|
1391
|
+
const ackUpToSeq = pendingAckSeq;
|
|
1392
|
+
const inlineAckGeneration = ackUpToSeq > 0 ? client._delivery.captureP2PInlineAckGeneration() : null;
|
|
1379
1393
|
const result = await client._callRawV2Rpc('message.v2.pull', {
|
|
1380
1394
|
after_seq: producerAfterSeq,
|
|
1381
1395
|
limit,
|
|
1396
|
+
...(ackUpToSeq > 0 ? { ack_up_to_seq: ackUpToSeq } : {}),
|
|
1382
1397
|
...(producerVolatileCursor ? { after_volatile_cursor: producerVolatileCursor } : {}),
|
|
1383
1398
|
...(opts?.force ? { force: true } : {}),
|
|
1384
1399
|
}, pullGateKey);
|
|
1385
1400
|
if (pipelineStopped)
|
|
1386
1401
|
break;
|
|
1402
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
1387
1403
|
const rawPageMessages = (Array.isArray(result?.messages) ? result.messages : []);
|
|
1388
|
-
const completed = new Promise((resolve) => { pipelineResume.current = resolve; });
|
|
1389
1404
|
const enqueued = await pipelineQueue.put({
|
|
1390
1405
|
result,
|
|
1391
1406
|
afterSeq: producerAfterSeq,
|
|
1392
|
-
ackUpToSeq
|
|
1393
|
-
inlineAckGeneration
|
|
1407
|
+
ackUpToSeq,
|
|
1408
|
+
inlineAckGeneration,
|
|
1394
1409
|
requestedVolatileCursor,
|
|
1395
1410
|
weight: rawPageMessages.length,
|
|
1396
1411
|
}, rawPageMessages.length);
|
|
1397
1412
|
if (!enqueued || pipelineStopped)
|
|
1398
1413
|
break;
|
|
1399
|
-
await completed;
|
|
1400
|
-
if (pipelineStopped)
|
|
1401
|
-
break;
|
|
1402
1414
|
const volatileMessages = client._delivery.volatileMessages?.(rawPageMessages) ?? [];
|
|
1403
1415
|
if (volatileMessages.length > 0)
|
|
1404
1416
|
break;
|
|
@@ -1406,7 +1418,7 @@ export class V2E2EECoordinator {
|
|
|
1406
1418
|
const seqs = messages
|
|
1407
1419
|
.map((msg) => Number(msg.seq ?? 0))
|
|
1408
1420
|
.filter((seq) => Number.isFinite(seq) && seq > 0);
|
|
1409
|
-
const nextAfter = Math.max(
|
|
1421
|
+
const nextAfter = Math.max(producerAfterSeq, ...seqs);
|
|
1410
1422
|
const cursor = isJsonObject(result.cursor)
|
|
1411
1423
|
? result.cursor : null;
|
|
1412
1424
|
const shouldContinue = shouldContinueForwardPage({
|
|
@@ -1433,8 +1445,6 @@ export class V2E2EECoordinator {
|
|
|
1433
1445
|
};
|
|
1434
1446
|
const stopPipeline = async () => {
|
|
1435
1447
|
pipelineStopped = true;
|
|
1436
|
-
pipelineResume.current?.();
|
|
1437
|
-
pipelineResume.current = null;
|
|
1438
1448
|
pipelineQueue.close();
|
|
1439
1449
|
if (pipelineProducer) {
|
|
1440
1450
|
const producer = pipelineProducer;
|
|
@@ -1458,7 +1468,7 @@ export class V2E2EECoordinator {
|
|
|
1458
1468
|
pageCount += 1;
|
|
1459
1469
|
const requestedVolatileCursor = pipelinePage?.requestedVolatileCursor ?? volatileCursor;
|
|
1460
1470
|
const ackUpToSeq = pipelinePage?.ackUpToSeq ?? pendingAckSeq;
|
|
1461
|
-
const inlineAckGeneration = pipelinePage
|
|
1471
|
+
const inlineAckGeneration = pipelinePage ? pipelinePage.inlineAckGeneration : (ackUpToSeq > 0
|
|
1462
1472
|
? client._delivery.captureP2PInlineAckGeneration()
|
|
1463
1473
|
: null);
|
|
1464
1474
|
client._clientLog.debug(`message.v2.pull page request: page=${pageCount}, after_seq=${nextAfterSeq}, limit=${limit}, ack_up_to_seq=${ackUpToSeq}, ns=${ns || '<none>'}`);
|
|
@@ -1487,25 +1497,31 @@ export class V2E2EECoordinator {
|
|
|
1487
1497
|
continue;
|
|
1488
1498
|
}
|
|
1489
1499
|
}
|
|
1500
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
1490
1501
|
if (ackUpToSeq > 0) {
|
|
1491
1502
|
const actualAckSeq = client._delivery.resolveP2PPullAckSeq(result, ackUpToSeq);
|
|
1492
1503
|
if (actualAckSeq >= ackUpToSeq) {
|
|
1493
1504
|
if (inlineAckGeneration !== null) {
|
|
1494
1505
|
client._delivery.onP2PV2PullAckResult(result, ackUpToSeq, inlineAckGeneration);
|
|
1495
1506
|
}
|
|
1496
|
-
pendingAckSeq
|
|
1507
|
+
if (pendingAckSeq <= ackUpToSeq)
|
|
1508
|
+
pendingAckSeq = 0;
|
|
1497
1509
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackUpToSeq);
|
|
1498
1510
|
this.clearForwardAck(ns, ackUpToSeq);
|
|
1499
1511
|
}
|
|
1500
1512
|
else {
|
|
1501
1513
|
client._clientLog.warn(`message.v2.pull piggyback ACK below target: requested=${ackUpToSeq}, actual=${actualAckSeq}; fallback terminal ACK`);
|
|
1502
|
-
await this.confirmForwardP2PAck(ackUpToSeq);
|
|
1503
|
-
pendingAckSeq = 0;
|
|
1504
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackUpToSeq);
|
|
1505
1514
|
}
|
|
1506
1515
|
}
|
|
1507
1516
|
const pageMessages = (Array.isArray(result?.messages) ? result.messages : []);
|
|
1508
1517
|
const volatileMessages = client._delivery.volatileMessages?.(pageMessages) ?? [];
|
|
1518
|
+
if (pipelinePage && volatileMessages.length > 0) {
|
|
1519
|
+
if (pipelineProducer)
|
|
1520
|
+
await pipelineProducer;
|
|
1521
|
+
pipelineProducer = null;
|
|
1522
|
+
pipelineRunning = false;
|
|
1523
|
+
pipelineQueue = new V2PullPageQueue(V2_PULL_PIPELINE_QUEUE_CAPACITY);
|
|
1524
|
+
}
|
|
1509
1525
|
if (volatileMessages.length > 0) {
|
|
1510
1526
|
decrypted.push(...await this.publishV2VolatileMessages(volatileMessages, 'pull', true));
|
|
1511
1527
|
volatileCursor = String(client._delivery.volatilePullCursor?.() ?? '').trim();
|
|
@@ -1531,6 +1547,13 @@ export class V2E2EECoordinator {
|
|
|
1531
1547
|
pageMaxSeq = Math.max(...seqs);
|
|
1532
1548
|
}
|
|
1533
1549
|
const pageContiguousSeq = contiguousPullSeq(pageContigBefore, seqs, result.contiguous_seq);
|
|
1550
|
+
if (!pipelineRunning && volatileMessages.length === 0 && shouldContinueForwardPage({
|
|
1551
|
+
rawCount: messages.length, nextAfterSeq, nextAfter: pageMaxSeq, limit,
|
|
1552
|
+
hasMoreField, hasMore, serverHead,
|
|
1553
|
+
observedUpper: Math.max(client._seqTracker.getMaxSeenSeq(ns), Number(client._pendingP2pPullUpper?.get?.(ns) ?? 0)),
|
|
1554
|
+
pendingAckSeq: 0,
|
|
1555
|
+
}))
|
|
1556
|
+
startPipeline(pageMaxSeq, volatileCursor);
|
|
1534
1557
|
const deferredKeyFetches = new Map();
|
|
1535
1558
|
let blockedSeq = 0;
|
|
1536
1559
|
const pageDecryptedBefore = decrypted.length;
|
|
@@ -1701,18 +1724,8 @@ export class V2E2EECoordinator {
|
|
|
1701
1724
|
|| (contigAdvanced && ackSeq > knownServerAckSeq));
|
|
1702
1725
|
if (ackNeeded) {
|
|
1703
1726
|
this.recordForwardAck(ns, ackSeq);
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
if (canContinuePage && !pipelineRunning) {
|
|
1707
|
-
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
1708
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
1709
|
-
client._clientLog.debug(`message.v2.pull queued piggyback auto-ack: ns=${ns}, ack_seq=${pendingAckSeq}, raw_count=${messages.length}`);
|
|
1710
|
-
}
|
|
1711
|
-
else {
|
|
1712
|
-
client._clientLog.debug(`message.v2.pull sending terminal auto-ack: ns=${ns}, ack_seq=${ackSeq}, raw_count=${messages.length}`);
|
|
1713
|
-
await this.confirmForwardP2PAck(ackSeq);
|
|
1714
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
1715
|
-
}
|
|
1727
|
+
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
1728
|
+
client._clientLog.debug(`message.v2.pull queued piggyback auto-ack: ns=${ns}, ack_seq=${pendingAckSeq}, raw_count=${messages.length}`);
|
|
1716
1729
|
}
|
|
1717
1730
|
}
|
|
1718
1731
|
if (!ns) {
|
|
@@ -1729,7 +1742,7 @@ export class V2E2EECoordinator {
|
|
|
1729
1742
|
currentSeq: client._seqTracker.getContiguousSeq(ns),
|
|
1730
1743
|
targetSeq: serverHead,
|
|
1731
1744
|
});
|
|
1732
|
-
const nextAfter = Math.max(
|
|
1745
|
+
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
1733
1746
|
const rawCount = messages.length;
|
|
1734
1747
|
if (blockedSeq > 0)
|
|
1735
1748
|
break;
|
|
@@ -1761,11 +1774,7 @@ export class V2E2EECoordinator {
|
|
|
1761
1774
|
&& volatileCursor !== requestedVolatileCursor;
|
|
1762
1775
|
if (!shouldContinuePersistent && !shouldContinueVolatile)
|
|
1763
1776
|
break;
|
|
1764
|
-
if (shouldContinueForPipeline && !pipelineRunning && limit >= V2_PULL_MAX_PAGE_LIMIT) {
|
|
1765
|
-
if (pendingAckSeq > 0) {
|
|
1766
|
-
await this.confirmForwardP2PAck(pendingAckSeq);
|
|
1767
|
-
pendingAckSeq = 0;
|
|
1768
|
-
}
|
|
1777
|
+
if (shouldContinueForPipeline && volatileMessages.length === 0 && !pipelineRunning && limit >= V2_PULL_MAX_PAGE_LIMIT) {
|
|
1769
1778
|
startPipeline(nextAfter, volatileCursor);
|
|
1770
1779
|
}
|
|
1771
1780
|
if (!pipelineRunning && pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
|
|
@@ -1775,14 +1784,10 @@ export class V2E2EECoordinator {
|
|
|
1775
1784
|
await client._rpcPipeline.yieldPullGate(pullGateKey, nextKey, true);
|
|
1776
1785
|
pullGateKey = nextKey;
|
|
1777
1786
|
}
|
|
1778
|
-
const tailDelayMs = v2PullTailDelayMs(rawCount, limit);
|
|
1787
|
+
const tailDelayMs = pipelineRunning ? 0 : v2PullTailDelayMs(rawCount, limit);
|
|
1779
1788
|
if (tailDelayMs > 0)
|
|
1780
1789
|
await v2Sleep(tailDelayMs);
|
|
1781
1790
|
nextAfterSeq = nextAfter;
|
|
1782
|
-
if (pipelinePage) {
|
|
1783
|
-
pipelineResume.current?.();
|
|
1784
|
-
pipelineResume.current = null;
|
|
1785
|
-
}
|
|
1786
1791
|
}
|
|
1787
1792
|
}
|
|
1788
1793
|
finally {
|
|
@@ -1790,11 +1795,14 @@ export class V2E2EECoordinator {
|
|
|
1790
1795
|
}
|
|
1791
1796
|
if (pageCount >= maxPages) {
|
|
1792
1797
|
client._clientLog.warn(`message.v2.pull reached max_pages=${maxPages} after_seq=${nextAfterSeq}`);
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1798
|
+
}
|
|
1799
|
+
if (pendingAckSeq > 0) {
|
|
1800
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
1801
|
+
client._clientLog.debug(`message.v2.pull flushing pending auto-ack: ns=${ns}, ack_seq=${pendingAckSeq}`);
|
|
1802
|
+
const ackToFlush = pendingAckSeq;
|
|
1803
|
+
await this.confirmForwardP2PAck(ackToFlush);
|
|
1804
|
+
if (pendingAckSeq <= ackToFlush)
|
|
1796
1805
|
pendingAckSeq = 0;
|
|
1797
|
-
}
|
|
1798
1806
|
}
|
|
1799
1807
|
client._clientLog.debug(`message.v2.pull done: requested_after_seq=${afterSeq}, pages=${pageCount}, decrypted=${decrypted.length}, ns=${ns || '<none>'}`);
|
|
1800
1808
|
return decrypted;
|
|
@@ -1881,8 +1889,10 @@ export class V2E2EECoordinator {
|
|
|
1881
1889
|
}
|
|
1882
1890
|
async confirmForwardP2PAck(upToSeq) {
|
|
1883
1891
|
const ns = this.client._aid ? `p2p:${this.client._aid}` : '';
|
|
1892
|
+
const generation = Number(this.client._v2RuntimeGeneration ?? 0);
|
|
1884
1893
|
try {
|
|
1885
1894
|
const result = await this.ackV2ForForward(upToSeq);
|
|
1895
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
1886
1896
|
const actualAckSeq = this.client._delivery.resolveForwardAckSeq(result, upToSeq);
|
|
1887
1897
|
if (actualAckSeq < upToSeq) {
|
|
1888
1898
|
throw new E2EEError(`message.v2.ack server ACK watermark ${actualAckSeq} is below requested ${upToSeq}`);
|
|
@@ -1890,7 +1900,9 @@ export class V2E2EECoordinator {
|
|
|
1890
1900
|
this.clearForwardAck(ns, upToSeq);
|
|
1891
1901
|
}
|
|
1892
1902
|
catch (exc) {
|
|
1893
|
-
this.
|
|
1903
|
+
if (Number(this.client._v2RuntimeGeneration ?? 0) === generation
|
|
1904
|
+
&& this.client._rpcPipeline?.isPullNamespaceCurrent?.(ns) !== false)
|
|
1905
|
+
this.recordForwardAck(ns, upToSeq);
|
|
1894
1906
|
throw exc;
|
|
1895
1907
|
}
|
|
1896
1908
|
}
|
|
@@ -2334,7 +2346,6 @@ export class V2E2EECoordinator {
|
|
|
2334
2346
|
const pipelineQueue = new V2PullPageQueue(V2_PULL_PIPELINE_QUEUE_CAPACITY);
|
|
2335
2347
|
let pipelineProducer = null;
|
|
2336
2348
|
let pipelineStopped = false;
|
|
2337
|
-
const pipelineResume = { current: null };
|
|
2338
2349
|
const startPipeline = (startAfterSeq) => {
|
|
2339
2350
|
if (pipelineRunning || pageCount >= maxPages || limit < V2_PULL_MAX_PAGE_LIMIT || !ownsCursor)
|
|
2340
2351
|
return;
|
|
@@ -2344,35 +2355,36 @@ export class V2E2EECoordinator {
|
|
|
2344
2355
|
for (let produced = pageCount; produced < maxPages; produced += 1) {
|
|
2345
2356
|
if (pipelineStopped)
|
|
2346
2357
|
break;
|
|
2358
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
2359
|
+
const ackUpToSeq = pendingAckSeq;
|
|
2360
|
+
const inlineAckGeneration = ackUpToSeq > 0 ? client._delivery.captureGroupInlineAckGeneration() : null;
|
|
2347
2361
|
const result = await client._callRawV2Rpc('group.v2.pull', withExplicitGroupAid({
|
|
2348
2362
|
group_id: wireGroupId,
|
|
2349
2363
|
after_seq: producerAfterSeq,
|
|
2350
2364
|
limit,
|
|
2351
2365
|
...cursorParams,
|
|
2352
2366
|
...(opts?.force ? { force: true } : {}),
|
|
2367
|
+
...(ackUpToSeq > 0 ? { ack_up_to_seq: ackUpToSeq } : {}),
|
|
2353
2368
|
}, groupAid), pullGateKey);
|
|
2354
2369
|
if (pipelineStopped)
|
|
2355
2370
|
break;
|
|
2371
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
2356
2372
|
const pageMessages = (Array.isArray(result.messages) ? result.messages : []);
|
|
2357
|
-
const completed = new Promise((resolve) => { pipelineResume.current = resolve; });
|
|
2358
2373
|
const enqueued = await pipelineQueue.put({
|
|
2359
2374
|
result,
|
|
2360
2375
|
afterSeq: producerAfterSeq,
|
|
2361
|
-
ackUpToSeq
|
|
2362
|
-
inlineAckGeneration
|
|
2376
|
+
ackUpToSeq,
|
|
2377
|
+
inlineAckGeneration,
|
|
2363
2378
|
requestedVolatileCursor: '',
|
|
2364
2379
|
weight: pageMessages.length,
|
|
2365
2380
|
}, pageMessages.length);
|
|
2366
2381
|
if (!enqueued || pipelineStopped)
|
|
2367
2382
|
break;
|
|
2368
|
-
await completed;
|
|
2369
|
-
if (pipelineStopped)
|
|
2370
|
-
break;
|
|
2371
2383
|
const messages = deduplicateForwardPageMessages(pageMessages, producerAfterSeq);
|
|
2372
2384
|
const seqs = messages
|
|
2373
2385
|
.map((msg) => Number(msg.seq ?? 0))
|
|
2374
2386
|
.filter((seq) => Number.isFinite(seq) && seq > 0);
|
|
2375
|
-
const nextAfter = Math.max(
|
|
2387
|
+
const nextAfter = Math.max(producerAfterSeq, ...seqs);
|
|
2376
2388
|
const cursor = isJsonObject(result.cursor)
|
|
2377
2389
|
? result.cursor : null;
|
|
2378
2390
|
const shouldContinue = shouldContinueForwardPage({
|
|
@@ -2398,8 +2410,6 @@ export class V2E2EECoordinator {
|
|
|
2398
2410
|
};
|
|
2399
2411
|
const stopPipeline = async () => {
|
|
2400
2412
|
pipelineStopped = true;
|
|
2401
|
-
pipelineResume.current?.();
|
|
2402
|
-
pipelineResume.current = null;
|
|
2403
2413
|
pipelineQueue.close();
|
|
2404
2414
|
if (pipelineProducer) {
|
|
2405
2415
|
const producer = pipelineProducer;
|
|
@@ -2422,7 +2432,7 @@ export class V2E2EECoordinator {
|
|
|
2422
2432
|
}
|
|
2423
2433
|
pageCount += 1;
|
|
2424
2434
|
const ackUpToSeq = ownsCursor ? (pipelinePage?.ackUpToSeq ?? pendingAckSeq) : 0;
|
|
2425
|
-
const inlineAckGeneration = pipelinePage
|
|
2435
|
+
const inlineAckGeneration = pipelinePage ? pipelinePage.inlineAckGeneration : (ackUpToSeq > 0
|
|
2426
2436
|
? client._delivery.captureGroupInlineAckGeneration()
|
|
2427
2437
|
: null);
|
|
2428
2438
|
client._clientLog.debug(`group.v2.pull page request: group=${gid}, page=${pageCount}, after_seq=${nextAfterSeq}, limit=${limit}, ack_up_to_seq=${ackUpToSeq}, ns=${ns}`);
|
|
@@ -2441,21 +2451,21 @@ export class V2E2EECoordinator {
|
|
|
2441
2451
|
...(ackUpToSeq > 0 ? { ack_up_to_seq: ackUpToSeq } : {}),
|
|
2442
2452
|
}, groupAid), pullGateKey);
|
|
2443
2453
|
}
|
|
2454
|
+
if (ownsCursor)
|
|
2455
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
2444
2456
|
if (ackUpToSeq > 0) {
|
|
2445
2457
|
const actualAckSeq = client._delivery.resolveGroupPullAckSeq(result, ackUpToSeq);
|
|
2446
2458
|
if (actualAckSeq >= ackUpToSeq) {
|
|
2447
2459
|
if (inlineAckGeneration !== null) {
|
|
2448
2460
|
client._delivery.onGroupV2PullAckResult(gid, result, ackUpToSeq, inlineAckGeneration);
|
|
2449
2461
|
}
|
|
2450
|
-
pendingAckSeq
|
|
2462
|
+
if (pendingAckSeq <= ackUpToSeq)
|
|
2463
|
+
pendingAckSeq = 0;
|
|
2451
2464
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackUpToSeq);
|
|
2452
2465
|
this.clearForwardAck(ns, ackUpToSeq);
|
|
2453
2466
|
}
|
|
2454
2467
|
else {
|
|
2455
2468
|
client._clientLog.warn(`group.v2.pull piggyback ACK below target: group=${gid}, requested=${ackUpToSeq}, actual=${actualAckSeq}; fallback terminal ACK`);
|
|
2456
|
-
await this.confirmForwardGroupAck(gid, ackUpToSeq, groupAid);
|
|
2457
|
-
pendingAckSeq = 0;
|
|
2458
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackUpToSeq);
|
|
2459
2469
|
}
|
|
2460
2470
|
}
|
|
2461
2471
|
const resultGroupAid = String(result.group_aid ?? result.groupAid ?? '').trim();
|
|
@@ -2483,6 +2493,13 @@ export class V2E2EECoordinator {
|
|
|
2483
2493
|
pageMaxSeq = Math.max(...seqs);
|
|
2484
2494
|
}
|
|
2485
2495
|
const pageContiguousSeq = contiguousPullSeq(pageContigBefore, seqs, result.contiguous_seq);
|
|
2496
|
+
if (!pipelineRunning && ownsCursor && shouldContinueForwardPage({
|
|
2497
|
+
rawCount: messages.length, nextAfterSeq, nextAfter: pageMaxSeq, limit,
|
|
2498
|
+
hasMoreField, hasMore, serverHead,
|
|
2499
|
+
observedUpper: Math.max(client._seqTracker.getMaxSeenSeq(ns), Number(client._delivery.pendingPullUpper?.(ns) ?? 0)),
|
|
2500
|
+
pendingAckSeq: 0,
|
|
2501
|
+
}))
|
|
2502
|
+
startPipeline(pageMaxSeq);
|
|
2486
2503
|
const deferredKeyFetches = new Map();
|
|
2487
2504
|
let blockedSeq = 0;
|
|
2488
2505
|
const pageDecryptedBefore = decrypted.length;
|
|
@@ -2688,18 +2705,8 @@ export class V2E2EECoordinator {
|
|
|
2688
2705
|
|| (contigAdvanced && ackSeq > knownServerCursorSeq));
|
|
2689
2706
|
if (ackNeeded) {
|
|
2690
2707
|
this.recordForwardAck(ns, ackSeq);
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
if (canContinuePage && !pipelineRunning) {
|
|
2694
|
-
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
2695
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
2696
|
-
client._clientLog.debug(`group.v2.pull queued piggyback auto-ack: group=${gid}, ns=${ns}, ack_seq=${pendingAckSeq}, raw_count=${messages.length}`);
|
|
2697
|
-
}
|
|
2698
|
-
else {
|
|
2699
|
-
client._clientLog.debug(`group.v2.pull sending terminal auto-ack: group=${gid}, ns=${ns}, ack_seq=${ackSeq}, raw_count=${messages.length}`);
|
|
2700
|
-
await this.confirmForwardGroupAck(gid, ackSeq, groupAid);
|
|
2701
|
-
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
2702
|
-
}
|
|
2708
|
+
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
2709
|
+
client._clientLog.debug(`group.v2.pull queued piggyback auto-ack: group=${gid}, ns=${ns}, ack_seq=${pendingAckSeq}, raw_count=${messages.length}`);
|
|
2703
2710
|
}
|
|
2704
2711
|
client._delivery.syncProgress(ns, {
|
|
2705
2712
|
rawCount: messages.length,
|
|
@@ -2709,7 +2716,7 @@ export class V2E2EECoordinator {
|
|
|
2709
2716
|
currentSeq: client._seqTracker.getContiguousSeq(ns),
|
|
2710
2717
|
targetSeq: serverHead,
|
|
2711
2718
|
});
|
|
2712
|
-
const nextAfter = Math.max(
|
|
2719
|
+
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
2713
2720
|
if (!ownsCursor)
|
|
2714
2721
|
break;
|
|
2715
2722
|
const rawCount = messages.length;
|
|
@@ -2740,10 +2747,6 @@ export class V2E2EECoordinator {
|
|
|
2740
2747
|
if (!shouldContinue)
|
|
2741
2748
|
break;
|
|
2742
2749
|
if (shouldContinueForPipeline && !pipelineRunning && limit >= V2_PULL_MAX_PAGE_LIMIT) {
|
|
2743
|
-
if (pendingAckSeq > 0) {
|
|
2744
|
-
await this.confirmForwardGroupAck(gid, pendingAckSeq, groupAid);
|
|
2745
|
-
pendingAckSeq = 0;
|
|
2746
|
-
}
|
|
2747
2750
|
startPipeline(nextAfter);
|
|
2748
2751
|
}
|
|
2749
2752
|
if (!pipelineRunning && pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
|
|
@@ -2754,14 +2757,10 @@ export class V2E2EECoordinator {
|
|
|
2754
2757
|
await client._rpcPipeline.yieldPullGate(pullGateKey, nextKey, true);
|
|
2755
2758
|
pullGateKey = nextKey;
|
|
2756
2759
|
}
|
|
2757
|
-
const tailDelayMs = v2PullTailDelayMs(rawCount, limit);
|
|
2760
|
+
const tailDelayMs = pipelineRunning ? 0 : v2PullTailDelayMs(rawCount, limit);
|
|
2758
2761
|
if (tailDelayMs > 0)
|
|
2759
2762
|
await v2Sleep(tailDelayMs);
|
|
2760
2763
|
nextAfterSeq = nextAfter;
|
|
2761
|
-
if (pipelinePage) {
|
|
2762
|
-
pipelineResume.current?.();
|
|
2763
|
-
pipelineResume.current = null;
|
|
2764
|
-
}
|
|
2765
2764
|
}
|
|
2766
2765
|
}
|
|
2767
2766
|
finally {
|
|
@@ -2769,11 +2768,14 @@ export class V2E2EECoordinator {
|
|
|
2769
2768
|
}
|
|
2770
2769
|
if (pageCount >= maxPages) {
|
|
2771
2770
|
client._clientLog.warn(`group.v2.pull reached max_pages=${maxPages} group=${gid} after_seq=${nextAfterSeq}`);
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2771
|
+
}
|
|
2772
|
+
if (pendingAckSeq > 0) {
|
|
2773
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
2774
|
+
client._clientLog.debug(`group.v2.pull flushing pending auto-ack: group=${gid}, ns=${ns}, ack_seq=${pendingAckSeq}`);
|
|
2775
|
+
const ackToFlush = pendingAckSeq;
|
|
2776
|
+
await this.confirmForwardGroupAck(gid, ackToFlush, groupAid);
|
|
2777
|
+
if (pendingAckSeq <= ackToFlush)
|
|
2775
2778
|
pendingAckSeq = 0;
|
|
2776
|
-
}
|
|
2777
2779
|
}
|
|
2778
2780
|
client._clientLog.debug(`group.v2.pull done: group=${gid}, requested_after_seq=${afterSeq}, pages=${pageCount}, decrypted=${decrypted.length}, ns=${ns}`);
|
|
2779
2781
|
return decrypted;
|
|
@@ -2794,8 +2796,10 @@ export class V2E2EECoordinator {
|
|
|
2794
2796
|
}
|
|
2795
2797
|
async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
|
|
2796
2798
|
const ns = `group:${String(groupId ?? '').trim()}`;
|
|
2799
|
+
const generation = Number(this.client._v2RuntimeGeneration ?? 0);
|
|
2797
2800
|
try {
|
|
2798
2801
|
const result = await this.ackGroupV2ForForward(groupId, upToSeq, groupAid);
|
|
2802
|
+
this.ensureDeliveryCurrent(ns, generation);
|
|
2799
2803
|
const actualAckSeq = this.client._delivery.resolveForwardAckSeq(result, upToSeq);
|
|
2800
2804
|
if (actualAckSeq < upToSeq) {
|
|
2801
2805
|
throw new E2EEError(`group.v2.ack server ACK watermark ${actualAckSeq} is below requested ${upToSeq}`);
|
|
@@ -2803,7 +2807,9 @@ export class V2E2EECoordinator {
|
|
|
2803
2807
|
this.clearForwardAck(ns, upToSeq);
|
|
2804
2808
|
}
|
|
2805
2809
|
catch (exc) {
|
|
2806
|
-
this.
|
|
2810
|
+
if (Number(this.client._v2RuntimeGeneration ?? 0) === generation
|
|
2811
|
+
&& this.client._rpcPipeline?.isPullNamespaceCurrent?.(ns) !== false)
|
|
2812
|
+
this.recordForwardAck(ns, upToSeq);
|
|
2807
2813
|
throw exc;
|
|
2808
2814
|
}
|
|
2809
2815
|
}
|