@agentunion/fastaun 0.5.18 → 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 +172 -79
- package/_packed_docs/CHANGELOG.md +172 -79
- package/_packed_docs/INDEX.md +244 -116
- package/_packed_docs/KITE_DOCS_GUIDE.md +98 -69
- package/_packed_docs/agent.md/SCHEMA.md +245 -205
- 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/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +42 -15
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +4 -4
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +45 -134
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1072 -1072
- package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +5 -20
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +687 -668
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +19 -28
- 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 +4 -0
- 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 +68 -61
- 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 +279 -285
- 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 +271 -235
- package/_packed_docs/sdk/09-message-rpc-manual.md +47 -6
- package/_packed_docs/sdk/09-storage-rpc-manual.md +70 -68
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +63 -34
- package/_packed_docs/sdk/INDEX.md +105 -34
- 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 +15 -1
- package/dist/agent-md-schema.js +87 -24
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +54 -2
- package/dist/agent-md.js +637 -53
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +38 -59
- package/dist/aid-store.js +300 -265
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.js +30 -11
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts +6 -1
- package/dist/auth.js +500 -15
- package/dist/auth.js.map +1 -1
- package/dist/cert-utils.d.ts +44 -2
- package/dist/cert-utils.js +149 -49
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +11 -1
- package/dist/client/delivery.js +321 -62
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +1 -0
- package/dist/client/rpc-pipeline.js +142 -82
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +1 -0
- package/dist/client/v2-e2ee.js +166 -96
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +84 -1
- package/dist/client.js +780 -30
- package/dist/client.js.map +1 -1
- package/dist/errors.js +4 -3
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +9 -3
- package/dist/events.js +69 -11
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +83 -3
- package/dist/facades.js +100 -6
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +5 -0
- package/dist/keystore/aid-db.js +57 -0
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/index.d.ts +8 -0
- package/dist/keystore/local-identity-store.js +10 -3
- package/dist/keystore/local-identity-store.js.map +1 -1
- package/dist/keystore/local-token-store.d.ts +6 -1
- package/dist/keystore/local-token-store.js +24 -1
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +98 -0
- package/dist/org-protocol.js +1753 -0
- package/dist/org-protocol.js.map +1 -0
- package/dist/ownership-proof.d.ts +82 -5
- package/dist/ownership-proof.js +327 -31
- package/dist/ownership-proof.js.map +1 -1
- package/dist/ownership-v21.d.ts +196 -0
- package/dist/ownership-v21.js +712 -0
- package/dist/ownership-v21.js.map +1 -0
- package/dist/ownership-workflow.d.ts +87 -0
- package/dist/ownership-workflow.js +1182 -0
- package/dist/ownership-workflow.js.map +1 -0
- package/dist/seq-tracker.d.ts +1 -0
- package/dist/seq-tracker.js +10 -1
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +90 -1
- package/dist/tools/cross-sdk-agent.js +441 -7
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +8 -0
- package/dist/transport.js +118 -4
- package/dist/transport.js.map +1 -1
- package/dist/v2/e2ee/decrypt.d.ts +1 -0
- package/dist/v2/e2ee/decrypt.js +9 -1
- package/dist/v2/e2ee/decrypt.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -61,6 +61,7 @@ export declare class RpcPipeline {
|
|
|
61
61
|
background?: boolean;
|
|
62
62
|
pullGateKey?: string;
|
|
63
63
|
}): Promise<unknown>;
|
|
64
|
+
private observeBackgroundPullResponse;
|
|
64
65
|
private transportCallWithIdentityRecovery;
|
|
65
66
|
postprocessResult(method: string, params: RpcParams, result: unknown, options?: {
|
|
66
67
|
skipGroupState?: boolean;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as crypto from 'node:crypto';
|
|
2
2
|
import { normalizeSlotId, slotIsolationKey } from '../config.js';
|
|
3
3
|
import { certTimeError } from '../cert-utils.js';
|
|
4
|
+
import { orgRequestParams, validateOrgRequestJSON } from '../org-protocol.js';
|
|
5
|
+
import { canonicalJson as canonicalClientRequest } from '../v2/crypto/canonical.js';
|
|
4
6
|
import { ClientSignatureError, ConnectionError, PermissionError, TimeoutError, ValidationError } from '../errors.js';
|
|
5
7
|
import { ConnectionState, isJsonObject, } from '../types.js';
|
|
6
8
|
import { validateAIDFormat, validateGroupIDFormat } from '../validators.js';
|
|
@@ -113,6 +115,7 @@ function getCertFingerprint(certPem) {
|
|
|
113
115
|
/** 旧式 tryAcquirePullGate 的防并发窗口。 */
|
|
114
116
|
const PULL_GATE_STALE_MS = 35_000;
|
|
115
117
|
const PULL_GATE_OPERATION_TIMEOUT_MS = 35_000;
|
|
118
|
+
const PULL_GATE_MAX_ACTIVE = 4;
|
|
116
119
|
function sameIdentityAdmissionRejection(error, original) {
|
|
117
120
|
const errorCode = Number(error?.code);
|
|
118
121
|
const originalCode = Number(original?.code);
|
|
@@ -165,6 +168,7 @@ export class RpcPipeline {
|
|
|
165
168
|
}
|
|
166
169
|
async call(method, params) {
|
|
167
170
|
const client = this.runtime.client;
|
|
171
|
+
const generation = client._delivery?.captureInlineAckGeneration?.();
|
|
168
172
|
const tStart = Date.now();
|
|
169
173
|
const requestedAckSeq = method === 'message.ack' || method === 'message.v2.ack'
|
|
170
174
|
? Number(params?.seq
|
|
@@ -355,6 +359,9 @@ export class RpcPipeline {
|
|
|
355
359
|
return this.bindActivePullCancellation(method, p, request);
|
|
356
360
|
};
|
|
357
361
|
let result = await this.transportCallWithIdentityRecovery(invokeTransport, method, p);
|
|
362
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.()) {
|
|
363
|
+
this.observeBackgroundPullResponse(method, p, result, pullGateNamespace);
|
|
364
|
+
}
|
|
358
365
|
const sendResultModeSource = result;
|
|
359
366
|
result = await this.postprocessResult(method, p, result, {
|
|
360
367
|
skipGroupState: deferGroupReadyPostprocess,
|
|
@@ -370,6 +377,10 @@ export class RpcPipeline {
|
|
|
370
377
|
client._clientLog.debug(`call exit (error): method=${method} elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
|
|
371
378
|
throw err;
|
|
372
379
|
}
|
|
380
|
+
finally {
|
|
381
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.())
|
|
382
|
+
client._delivery?.requestBackgroundPullRecovery?.();
|
|
383
|
+
}
|
|
373
384
|
}
|
|
374
385
|
preflight(method, params) {
|
|
375
386
|
const client = this.runtime.client;
|
|
@@ -502,7 +513,10 @@ export class RpcPipeline {
|
|
|
502
513
|
}
|
|
503
514
|
applyClientSignature(method, params) {
|
|
504
515
|
try {
|
|
505
|
-
if (
|
|
516
|
+
if (method.startsWith('org.')) {
|
|
517
|
+
params.aad = orgRequestParams(method, params).aad;
|
|
518
|
+
}
|
|
519
|
+
else if (!SIGNED_METHODS.has(method)) {
|
|
506
520
|
return;
|
|
507
521
|
}
|
|
508
522
|
if (this.shouldSkipClientSignature(method, params)) {
|
|
@@ -527,8 +541,11 @@ export class RpcPipeline {
|
|
|
527
541
|
const currentAid = (internal && typeof internal === 'object')
|
|
528
542
|
? internal
|
|
529
543
|
: this.runtime.client._currentAid;
|
|
530
|
-
if (!currentAid?.privateKeyPem)
|
|
544
|
+
if (!currentAid?.privateKeyPem) {
|
|
545
|
+
if (method.startsWith('org.'))
|
|
546
|
+
throw new ClientSignatureError('组织请求签名身份不可用');
|
|
531
547
|
return;
|
|
548
|
+
}
|
|
532
549
|
try {
|
|
533
550
|
const aid = currentAid.aid;
|
|
534
551
|
const certPem = currentAid.certPem ?? '';
|
|
@@ -543,8 +560,16 @@ export class RpcPipeline {
|
|
|
543
560
|
paramsForHash[k] = v;
|
|
544
561
|
}
|
|
545
562
|
}
|
|
546
|
-
|
|
563
|
+
if (method.startsWith('org.'))
|
|
564
|
+
validateOrgRequestJSON(paramsForHash);
|
|
565
|
+
const paramsJson = method.startsWith('org.') ? new TextDecoder().decode(canonicalClientRequest(paramsForHash)) : stableStringify(paramsForHash);
|
|
547
566
|
const paramsHash = crypto.createHash('sha256').update(paramsJson, 'utf-8').digest('hex');
|
|
567
|
+
if (params.client_signature !== undefined) {
|
|
568
|
+
const existing = params.client_signature;
|
|
569
|
+
if (!isJsonObject(existing) || existing.aid !== aid || existing.cert_fingerprint !== getCertFingerprint(certPem) || existing.params_hash !== paramsHash || typeof existing.timestamp !== 'string' || !/^\d+$/.test(existing.timestamp) || typeof existing.signature !== 'string' || !crypto.verify('SHA256', Buffer.from(`${method}|${aid}|${existing.timestamp}|${paramsHash}`, 'utf-8'), crypto.createPublicKey(certPem), Buffer.from(existing.signature, 'base64')))
|
|
570
|
+
throw new Error('已有客户端签名与请求内容不一致');
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
548
573
|
const signData = Buffer.from(`${method}|${aid}|${ts}|${paramsHash}`, 'utf-8');
|
|
549
574
|
const privateKey = getSigningPrivateKey(currentAid.privateKeyPem);
|
|
550
575
|
const signature = crypto.sign('SHA256', signData, privateKey);
|
|
@@ -634,7 +659,7 @@ export class RpcPipeline {
|
|
|
634
659
|
const name = this.pullGateName(key);
|
|
635
660
|
let state = this.pullGateStates.get(name);
|
|
636
661
|
if (!state) {
|
|
637
|
-
state = {
|
|
662
|
+
state = { activeByNamespace: new Map(), foreground: [], background: [], byKey: new Map(), lifecycle: new Map(), watchdog: null };
|
|
638
663
|
this.pullGateStates.set(name, state);
|
|
639
664
|
}
|
|
640
665
|
this.startPullGateWatchdog(state, name);
|
|
@@ -665,23 +690,25 @@ export class RpcPipeline {
|
|
|
665
690
|
}
|
|
666
691
|
}
|
|
667
692
|
checkPullGate(state, name) {
|
|
668
|
-
const
|
|
669
|
-
if (
|
|
693
|
+
const activeJobs = [...state.activeByNamespace.values()];
|
|
694
|
+
if (activeJobs.length === 0) {
|
|
670
695
|
this.drainPullGate(state);
|
|
671
696
|
return;
|
|
672
697
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
698
|
+
for (const active of activeJobs) {
|
|
699
|
+
if (!active.pullingStartedAt || Date.now() - active.pullingStartedAt < this.pullGateOperationTimeoutMs())
|
|
700
|
+
continue;
|
|
701
|
+
if (active.timedOut)
|
|
702
|
+
continue;
|
|
703
|
+
active.timedOut = true;
|
|
704
|
+
active.invalidated = true;
|
|
705
|
+
active.cancel?.();
|
|
706
|
+
const timeout = new TimeoutError(`pull gate timeout: ${active.namespace}`, { retryable: true });
|
|
707
|
+
this.runtime.client._clientLog.warn(`pull gate watchdog timeout: gate=${name} key=${active.key} elapsed=${Date.now() - active.pullingStartedAt}ms`);
|
|
708
|
+
// 仅拒绝当前调用方;取消不敏感的 operation 仍可能运行,必须等其
|
|
709
|
+
// 真正 settle 后才释放 active,避免与后续 Pull 并发修改游标。
|
|
710
|
+
active.reject(timeout);
|
|
711
|
+
}
|
|
685
712
|
}
|
|
686
713
|
pullScopeKey(key) {
|
|
687
714
|
return key.split('|', 1)[0] ?? key;
|
|
@@ -696,7 +723,7 @@ export class RpcPipeline {
|
|
|
696
723
|
if (typeof cancel !== 'function' || !key)
|
|
697
724
|
return request;
|
|
698
725
|
const state = this.pullGateStates.get(this.pullGateName(key));
|
|
699
|
-
const active = state?.
|
|
726
|
+
const active = [...(state?.activeByNamespace.values() ?? [])].find((candidate) => candidate.key === key);
|
|
700
727
|
if (!active || active.key !== key || active.timedOut || active.invalidated)
|
|
701
728
|
return request;
|
|
702
729
|
const boundCancel = () => cancel.call(request);
|
|
@@ -734,8 +761,8 @@ export class RpcPipeline {
|
|
|
734
761
|
return true;
|
|
735
762
|
}
|
|
736
763
|
for (const state of this.pullGateStates.values()) {
|
|
737
|
-
const jobs = [state.
|
|
738
|
-
if (jobs.some((job) =>
|
|
764
|
+
const jobs = [...state.activeByNamespace.values(), ...state.foreground, ...state.background];
|
|
765
|
+
if (jobs.some((job) => this.pullScopeKey(job.key) === ns))
|
|
739
766
|
return true;
|
|
740
767
|
}
|
|
741
768
|
return false;
|
|
@@ -798,7 +825,7 @@ export class RpcPipeline {
|
|
|
798
825
|
const ns = this.pullScopeKey(namespace);
|
|
799
826
|
if (!ns)
|
|
800
827
|
return true;
|
|
801
|
-
const active = this.pullGateStates.get(this.pullGateName(ns))?.
|
|
828
|
+
const active = this.pullGateStates.get(this.pullGateName(ns))?.activeByNamespace.get(ns);
|
|
802
829
|
return !active || active.namespace !== ns || (!active.timedOut && !active.invalidated);
|
|
803
830
|
}
|
|
804
831
|
invalidatePulls() {
|
|
@@ -809,8 +836,8 @@ export class RpcPipeline {
|
|
|
809
836
|
const waits = [];
|
|
810
837
|
for (const state of this.pullGateStates.values()) {
|
|
811
838
|
const jobs = new Set();
|
|
812
|
-
|
|
813
|
-
jobs.add(
|
|
839
|
+
for (const active of state.activeByNamespace.values())
|
|
840
|
+
jobs.add(active);
|
|
814
841
|
for (const job of state.foreground)
|
|
815
842
|
jobs.add(job);
|
|
816
843
|
for (const job of state.background)
|
|
@@ -851,6 +878,9 @@ export class RpcPipeline {
|
|
|
851
878
|
return this.pullInvalidationWait !== null;
|
|
852
879
|
}
|
|
853
880
|
async runPullSerialized(key, operation, background = false) {
|
|
881
|
+
if (this.runtime.client._dispatcher?._isApplicationHandler?.()) {
|
|
882
|
+
throw new Error('pull cannot wait inside an application handler');
|
|
883
|
+
}
|
|
854
884
|
if (this.pullInvalidationInProgress()) {
|
|
855
885
|
throw new Error('pull invalidated');
|
|
856
886
|
}
|
|
@@ -865,7 +895,7 @@ export class RpcPipeline {
|
|
|
865
895
|
}
|
|
866
896
|
const state = this.pullGateState(key);
|
|
867
897
|
const namespace = this.pullScopeKey(key);
|
|
868
|
-
const active = state.
|
|
898
|
+
const active = [...state.activeByNamespace.values()].find((job) => job.key === key && !job.timedOut && !job.invalidated) ?? null;
|
|
869
899
|
const queuedForeground = state.foreground.find((job) => job.key === key && !job.timedOut && !job.invalidated);
|
|
870
900
|
const queuedBackground = state.background.find((job) => job.key === key && !job.timedOut && !job.invalidated);
|
|
871
901
|
const existing = background
|
|
@@ -925,8 +955,8 @@ export class RpcPipeline {
|
|
|
925
955
|
return;
|
|
926
956
|
const state = this.pullGateState(key);
|
|
927
957
|
const namespace = this.pullScopeKey(key);
|
|
928
|
-
const job = state.
|
|
929
|
-
if (!job ||
|
|
958
|
+
const job = [...state.activeByNamespace.values()].find((candidate) => candidate.key === key) ?? null;
|
|
959
|
+
if (!job || job.timedOut || job.invalidated)
|
|
930
960
|
return;
|
|
931
961
|
const replacementKey = String(nextKey || key);
|
|
932
962
|
if (state.byKey.get(job.key) === job)
|
|
@@ -945,7 +975,7 @@ export class RpcPipeline {
|
|
|
945
975
|
state.lifecycle.set(namespace, 'pulled');
|
|
946
976
|
job.suspended = true;
|
|
947
977
|
job.resume = new Promise((resolve) => { job.resumeResolve = resolve; });
|
|
948
|
-
state.
|
|
978
|
+
state.activeByNamespace.delete(namespace);
|
|
949
979
|
(job.background ? state.background : state.foreground).push(job);
|
|
950
980
|
this.drainPullGate(state);
|
|
951
981
|
if (job.resume) {
|
|
@@ -965,63 +995,68 @@ export class RpcPipeline {
|
|
|
965
995
|
if (!ns)
|
|
966
996
|
return;
|
|
967
997
|
const state = this.pullGateStates.get(this.pullGateName(ns));
|
|
968
|
-
if (!state || state.
|
|
998
|
+
if (!state || !state.activeByNamespace.has(ns))
|
|
969
999
|
return;
|
|
970
1000
|
state.lifecycle.set(ns, lifecycle);
|
|
971
1001
|
}
|
|
972
1002
|
drainPullGate(state) {
|
|
973
|
-
if (state.active)
|
|
974
|
-
return;
|
|
975
1003
|
const takeRunnable = (queue) => {
|
|
976
|
-
const index = queue.findIndex((candidate) => !this.hasInlineRealtimeGuard(this.pullScopeKey(candidate.key))
|
|
1004
|
+
const index = queue.findIndex((candidate) => (!this.hasInlineRealtimeGuard(this.pullScopeKey(candidate.key))
|
|
1005
|
+
&& !state.activeByNamespace.has(candidate.namespace)));
|
|
977
1006
|
return index >= 0 ? queue.splice(index, 1)[0] : undefined;
|
|
978
1007
|
};
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
job.
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
job.resume = null;
|
|
993
|
-
job.resumeResolve = null;
|
|
994
|
-
if (job.suspended) {
|
|
995
|
-
job.suspended = false;
|
|
996
|
-
resumeResolve?.();
|
|
997
|
-
return;
|
|
998
|
-
}
|
|
999
|
-
job.running = true;
|
|
1000
|
-
const operationPromise = this.executePullOperation(job.operation, job.background);
|
|
1001
|
-
let failed = false;
|
|
1002
|
-
void operationPromise
|
|
1003
|
-
.then((value) => { if (!job.timedOut && !job.invalidated)
|
|
1004
|
-
job.resolve(value); }, (error) => {
|
|
1005
|
-
failed = true;
|
|
1006
|
-
if (!job.timedOut && !job.invalidated)
|
|
1007
|
-
job.reject(error);
|
|
1008
|
-
})
|
|
1009
|
-
.finally(() => {
|
|
1010
|
-
state.lifecycle.set(job.namespace, 'idle');
|
|
1011
|
-
if (state.active === job)
|
|
1012
|
-
state.active = null;
|
|
1013
|
-
if (state.byKey.get(job.key) === job)
|
|
1014
|
-
state.byKey.delete(job.key);
|
|
1015
|
-
this.drainPullGate(state);
|
|
1016
|
-
job.settledResolve?.();
|
|
1017
|
-
job.settledResolve = null;
|
|
1018
|
-
if (!job.invalidated) {
|
|
1019
|
-
this.runtime.client._delivery?.onPullGateIdle?.(job.namespace);
|
|
1008
|
+
while (state.activeByNamespace.size < PULL_GATE_MAX_ACTIVE) {
|
|
1009
|
+
const foregroundJob = takeRunnable(state.foreground);
|
|
1010
|
+
const foregroundDrained = foregroundJob !== undefined && state.foreground.length === 0;
|
|
1011
|
+
const job = foregroundJob ?? takeRunnable(state.background);
|
|
1012
|
+
if (!job)
|
|
1013
|
+
break;
|
|
1014
|
+
state.activeByNamespace.set(job.namespace, job);
|
|
1015
|
+
this.runtime.client._delivery?.syncStarted?.(job.namespace);
|
|
1016
|
+
if (foregroundDrained)
|
|
1017
|
+
this.runtime.client._delivery?.onForegroundPullsDrained?.();
|
|
1018
|
+
if (job.timer) {
|
|
1019
|
+
clearTimeout(job.timer);
|
|
1020
|
+
job.timer = null;
|
|
1020
1021
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1022
|
+
job.pullingStartedAt = Date.now();
|
|
1023
|
+
job.timedOut = false;
|
|
1024
|
+
state.lifecycle.set(job.namespace, 'pulling');
|
|
1025
|
+
const resumeResolve = job.resumeResolve;
|
|
1026
|
+
job.resume = null;
|
|
1027
|
+
job.resumeResolve = null;
|
|
1028
|
+
if (job.suspended) {
|
|
1029
|
+
job.suspended = false;
|
|
1030
|
+
resumeResolve?.();
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
job.running = true;
|
|
1034
|
+
const operationPromise = this.executePullOperation(job.operation, job.background);
|
|
1035
|
+
let failed = false;
|
|
1036
|
+
void operationPromise
|
|
1037
|
+
.then((value) => { if (!job.timedOut && !job.invalidated)
|
|
1038
|
+
job.resolve(value); }, (error) => {
|
|
1039
|
+
failed = true;
|
|
1040
|
+
if (!job.timedOut && !job.invalidated)
|
|
1041
|
+
job.reject(error);
|
|
1042
|
+
})
|
|
1043
|
+
.finally(() => {
|
|
1044
|
+
state.lifecycle.set(job.namespace, 'idle');
|
|
1045
|
+
if (state.activeByNamespace.get(job.namespace) === job)
|
|
1046
|
+
state.activeByNamespace.delete(job.namespace);
|
|
1047
|
+
if (state.byKey.get(job.key) === job)
|
|
1048
|
+
state.byKey.delete(job.key);
|
|
1049
|
+
this.drainPullGate(state);
|
|
1050
|
+
job.settledResolve?.();
|
|
1051
|
+
job.settledResolve = null;
|
|
1052
|
+
if (!job.invalidated) {
|
|
1053
|
+
this.runtime.client._delivery?.onPullGateIdle?.(job.namespace);
|
|
1054
|
+
}
|
|
1055
|
+
if (failed || job.invalidated)
|
|
1056
|
+
this.runtime.client._delivery?.onPullAborted?.();
|
|
1057
|
+
this.notifyPullDrainedIfIdle();
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1025
1060
|
}
|
|
1026
1061
|
notifyPullDrainedIfIdle() {
|
|
1027
1062
|
if (this.pullDrainedCheckQueued)
|
|
@@ -1037,7 +1072,7 @@ export class RpcPipeline {
|
|
|
1037
1072
|
}
|
|
1038
1073
|
notifyPullDrainedIfIdleStable() {
|
|
1039
1074
|
for (const state of this.pullGateStates.values()) {
|
|
1040
|
-
if (state.
|
|
1075
|
+
if (state.activeByNamespace.size > 0 || state.foreground.length > 0 || state.background.length > 0)
|
|
1041
1076
|
return;
|
|
1042
1077
|
}
|
|
1043
1078
|
const client = this.runtime.client;
|
|
@@ -1055,7 +1090,7 @@ export class RpcPipeline {
|
|
|
1055
1090
|
const { timeout, trace, signed = true, background = false, pullGateKey = '' } = opts;
|
|
1056
1091
|
const client = this.runtime.client;
|
|
1057
1092
|
const payload = params ? { ...params } : {};
|
|
1058
|
-
if (signed) {
|
|
1093
|
+
if (signed || method.startsWith('org.')) {
|
|
1059
1094
|
this.applyClientSignature(method, payload);
|
|
1060
1095
|
}
|
|
1061
1096
|
const invokeTransport = () => {
|
|
@@ -1070,9 +1105,34 @@ export class RpcPipeline {
|
|
|
1070
1105
|
request = client._transport.call(method, payload);
|
|
1071
1106
|
return this.bindActivePullCancellation(method, payload, request, pullGateKey);
|
|
1072
1107
|
};
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1108
|
+
const generation = client._delivery?.captureInlineAckGeneration?.();
|
|
1109
|
+
try {
|
|
1110
|
+
const result = await this.transportCallWithIdentityRecovery(invokeTransport, method, payload);
|
|
1111
|
+
this.throwIfPullInvalidated(this.pullScopeKey(pullGateKey || this.pullGateKeyForCall(method, payload)));
|
|
1112
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.()) {
|
|
1113
|
+
this.observeBackgroundPullResponse(method, payload, result, pullGateKey);
|
|
1114
|
+
}
|
|
1115
|
+
return result;
|
|
1116
|
+
}
|
|
1117
|
+
finally {
|
|
1118
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.())
|
|
1119
|
+
client._delivery?.requestBackgroundPullRecovery?.();
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
observeBackgroundPullResponse(method, params, result, key = '') {
|
|
1123
|
+
if (!['message.pull', 'message.v2.pull', 'group.pull', 'group.v2.pull', 'group.pull_events'].includes(method)
|
|
1124
|
+
|| params.force === true || params.window_mode === 'tail')
|
|
1125
|
+
return;
|
|
1126
|
+
const client = this.runtime.client;
|
|
1127
|
+
if (method.startsWith('group.') && !this.groupCursorTargetsCurrentInstance(params))
|
|
1128
|
+
return;
|
|
1129
|
+
const explicitCursor = this.explicitGroupCursorParams(params);
|
|
1130
|
+
if (method.startsWith('group.') && !this.groupCursorTargetsCurrentInstance(explicitCursor))
|
|
1131
|
+
return;
|
|
1132
|
+
const ns = this.pullScopeKey(key) || (method === 'group.pull_events'
|
|
1133
|
+
? `group_event:${String(params.group_id ?? params.group_aid ?? '')}`
|
|
1134
|
+
: method.startsWith('group.') ? `group:${String(params.group_id ?? params.group_aid ?? '')}` : `p2p:${client._aid}`);
|
|
1135
|
+
client._delivery?.observeBackgroundPullResponse?.(ns, Number(params.after_seq ?? params.after_event_seq ?? 0), result, Number(params.limit ?? 50));
|
|
1076
1136
|
}
|
|
1077
1137
|
async transportCallWithIdentityRecovery(operation, method, params) {
|
|
1078
1138
|
try {
|