@agentunion/fastaun 0.5.33 → 0.5.35
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 +59 -2
- package/README.md +28 -26
- package/_packed_docs/CHANGELOG.md +59 -2
- package/_packed_docs/INDEX.md +26 -12
- package/_packed_docs/KITE_DOCS_GUIDE.md +17 -11
- package/_packed_docs/agent.md/SCHEMA.md +1 -1
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +2 -2
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +58 -8
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +17 -17
- package/_packed_docs/protocol/echo-probe-gateway.md +99 -0
- package/_packed_docs/protocol/echo-probe-sdk.md +91 -0
- package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +464 -316
- package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +499 -304
- package/_packed_docs/sdk/0.5.34-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +133 -0
- package/_packed_docs/sdk/0.5.34-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +107 -0
- package/_packed_docs/sdk/0.5.35-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +189 -0
- package/_packed_docs/sdk/0.5.35-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +204 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +16 -13
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +13 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +19 -9
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +87 -20
- package/_packed_docs/sdk/09-collab-rpc-manual.md +48 -30
- package/_packed_docs/sdk/09-custody-api-manual.md +3 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +60 -13
- package/_packed_docs/sdk/09-message-rpc-manual.md +22 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -1
- package/_packed_docs/sdk/09-payload-reference.md +9 -8
- package/_packed_docs/sdk/09-proxy-rpc-manual.md +20 -14
- package/_packed_docs/sdk/09-storage-rpc-manual.md +1698 -1659
- package/_packed_docs/sdk/09-stream-rpc-manual.md +33 -20
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +19 -17
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +125 -30
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +109 -33
- package/_packed_docs/sdk/INDEX.md +30 -18
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +1 -1
- 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 +5 -5
- 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 +5 -5
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +9 -9
- package/_packed_docs/sdk/README.md +11 -6
- package/_packed_docs//346/266/210/346/201/257/345/274/271/346/200/247/350/241/245/346/213/211/351/200/232/351/201/223/345/256/236/346/226/275/350/256/241/345/210/222.md +400 -0
- package/_packed_docs//346/266/210/346/201/257/345/274/271/346/200/247/350/241/245/346/213/211/351/200/232/351/201/223/346/226/271/346/241/210.md +485 -0
- package/dist/auth.js +39 -45
- package/dist/auth.js.map +1 -1
- package/dist/client/control-messages.js +2 -2
- package/dist/client/control-messages.js.map +1 -1
- package/dist/client/delivery.d.ts +12 -1
- package/dist/client/delivery.js +281 -46
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/lifecycle.js +13 -1
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-budget.d.ts +21 -0
- package/dist/client/rpc-budget.js +82 -0
- package/dist/client/rpc-budget.js.map +1 -0
- package/dist/client/rpc-pipeline.d.ts +5 -0
- package/dist/client/rpc-pipeline.js +227 -63
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/sync-channels.d.ts +90 -0
- package/dist/client/sync-channels.js +508 -0
- package/dist/client/sync-channels.js.map +1 -0
- package/dist/client/v2-e2ee.d.ts +5 -1
- package/dist/client/v2-e2ee.js +420 -303
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +17 -0
- package/dist/client.js +373 -50
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +1 -0
- package/dist/events.js +5 -0
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mail-client.d.ts +101 -0
- package/dist/mail-client.js +369 -0
- package/dist/mail-client.js.map +1 -0
- package/dist/pubsub/binding.js +23 -3
- package/dist/pubsub/binding.js.map +1 -1
- package/dist/pubsub/channel.d.ts +15 -3
- package/dist/pubsub/channel.js +114 -7
- package/dist/pubsub/channel.js.map +1 -1
- package/dist/pubsub/client.d.ts +17 -2
- package/dist/pubsub/client.js +205 -40
- package/dist/pubsub/client.js.map +1 -1
- package/dist/pubsub/credentials.d.ts +3 -0
- package/dist/pubsub/credentials.js +57 -20
- package/dist/pubsub/credentials.js.map +1 -1
- package/dist/pubsub/index.d.ts +5 -2
- package/dist/pubsub/index.js +70 -54
- package/dist/pubsub/index.js.map +1 -1
- package/dist/pubsub/service.d.ts +9 -0
- package/dist/pubsub/service.js +266 -20
- package/dist/pubsub/service.js.map +1 -1
- package/dist/pubsub/types.d.ts +13 -1
- package/dist/storage/lowlevel.d.ts +3 -1
- package/dist/storage/lowlevel.js +13 -0
- package/dist/storage/lowlevel.js.map +1 -1
- package/dist/storage/types.d.ts +10 -0
- package/dist/storage/types.js.map +1 -1
- package/dist/storage/vfs.d.ts +3 -1
- package/dist/storage/vfs.js +2 -2
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +55 -5
- package/dist/tools/cross-sdk-agent.js +88 -21
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +16 -0
- package/dist/transport.js +129 -7
- package/dist/transport.js.map +1 -1
- package/dist/udp-standby.d.ts +89 -0
- package/dist/udp-standby.js +487 -0
- package/dist/udp-standby.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
- package/scripts/patch-imapflow-external.mjs +69 -0
package/dist/transport.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { EventDispatcher } from './events.js';
|
|
|
11
11
|
import { type ModuleLogger } from './logger.js';
|
|
12
12
|
import { type JsonObject, type RpcMessage, type RpcParams, type RpcResult } from './types.js';
|
|
13
13
|
import { type ServiceEventVerificationResult } from './org-protocol.js';
|
|
14
|
+
import { RpcBudget } from './client/rpc-budget.js';
|
|
14
15
|
export type RpcBackground = false | true | 'event' | 'pull';
|
|
15
16
|
/** 断线回调,closeCode 为 WebSocket close code(1006 = 网络异常断开,其他 = 服务端主动关闭) */
|
|
16
17
|
export type DisconnectCallback = (error: Error | null, closeCode?: number) => void | Promise<void>;
|
|
@@ -26,6 +27,7 @@ export declare function shortRpcViaNetworkActor(url: string, method: string, par
|
|
|
26
27
|
* WebSocket JSON-RPC 2.0 传输层
|
|
27
28
|
*/
|
|
28
29
|
export declare class RPCTransport {
|
|
30
|
+
readonly rpcBudget: RpcBudget;
|
|
29
31
|
private _logger;
|
|
30
32
|
private _dispatcher;
|
|
31
33
|
private _serviceEventVerifier;
|
|
@@ -67,8 +69,15 @@ export declare class RPCTransport {
|
|
|
67
69
|
private _riskDeliveries;
|
|
68
70
|
private _idCounter;
|
|
69
71
|
private _metaObserver;
|
|
72
|
+
private _syncControlObserver;
|
|
73
|
+
private _syncAdmission;
|
|
74
|
+
private _syncAuxiliary;
|
|
75
|
+
private readonly _budgetWaiters;
|
|
70
76
|
private _requestAdmission;
|
|
71
77
|
private _requestCheck;
|
|
78
|
+
private _standbyGate;
|
|
79
|
+
private _businessActivity;
|
|
80
|
+
private _standbyAuthParams;
|
|
72
81
|
private _riskControlHandler;
|
|
73
82
|
private _classMessageHandler;
|
|
74
83
|
private _protocolMetaObserver;
|
|
@@ -100,6 +109,8 @@ export declare class RPCTransport {
|
|
|
100
109
|
};
|
|
101
110
|
constructor(opts: {
|
|
102
111
|
eventDispatcher: EventDispatcher;
|
|
112
|
+
rpcBudget?: RpcBudget;
|
|
113
|
+
syncAuxiliary?: boolean;
|
|
103
114
|
timeout?: number;
|
|
104
115
|
onDisconnect?: DisconnectCallback | null;
|
|
105
116
|
verifySsl?: boolean;
|
|
@@ -121,6 +132,7 @@ export declare class RPCTransport {
|
|
|
121
132
|
setConnectTimeout(timeout: number): void;
|
|
122
133
|
/** 当前是否仍有可用的 WebSocket。 */
|
|
123
134
|
isConnected(): boolean;
|
|
135
|
+
setStandbyGate(gate: ((method: string, deadline: number, signal?: AbortSignal) => Promise<() => void>) | null, inbound?: (() => void) | null, authentication?: ((params: RpcParams) => RpcParams) | null): void;
|
|
124
136
|
/**
|
|
125
137
|
* 注册 RPC envelope _meta 字段观察者;observer(meta) 在每次成功 RPC 时调用。
|
|
126
138
|
*
|
|
@@ -137,6 +149,9 @@ export declare class RPCTransport {
|
|
|
137
149
|
private _finishRiskDelivery;
|
|
138
150
|
private _receiveRiskControl;
|
|
139
151
|
private _dispatchRiskControl;
|
|
152
|
+
setSyncControlObserver(observer: ((meta: Record<string, unknown>, method: string, params: JsonObject) => void) | null): void;
|
|
153
|
+
setSyncAdmission(policy: JsonObject | null): void;
|
|
154
|
+
private _checkSyncAdmission;
|
|
140
155
|
setProtocolMetaObserver(observer: MetaObserver | null): void;
|
|
141
156
|
setProtocolDisconnectCallback(callback: DisconnectCallback | null): void;
|
|
142
157
|
waitForPending(timeoutMs: number, signal?: AbortSignal): Promise<void>;
|
|
@@ -177,6 +192,7 @@ export declare class RPCTransport {
|
|
|
177
192
|
call(method: string, params?: RpcParams, timeout?: number, trace?: string, background?: RpcBackground): Promise<RpcResult>;
|
|
178
193
|
private _callWithSent;
|
|
179
194
|
private _call;
|
|
195
|
+
private _callWithAdmission;
|
|
180
196
|
private _callAdmitted;
|
|
181
197
|
private _callLocal;
|
|
182
198
|
/** 发送 JSON-RPC 2.0 Notification,不分配 id,也不等待响应。 */
|
package/dist/transport.js
CHANGED
|
@@ -16,6 +16,7 @@ import { isJsonObject } from './types.js';
|
|
|
16
16
|
import { parseJsonStrict, validateOrgRequestJSON } from './org-protocol.js';
|
|
17
17
|
import { RiskController } from './risk-control.js';
|
|
18
18
|
import { messageClassOf } from './client/control-messages.js';
|
|
19
|
+
import { RpcBudget } from './client/rpc-budget.js';
|
|
19
20
|
const MAX_WS_PAYLOAD_SIZE = 1_000_000;
|
|
20
21
|
const MAX_RPC_INFLIGHT = 16;
|
|
21
22
|
const MAX_BACKGROUND_RPC_INFLIGHT = 8;
|
|
@@ -550,6 +551,7 @@ export function shortRpcViaNetworkActor(url, method, params, verifySsl = false)
|
|
|
550
551
|
* WebSocket JSON-RPC 2.0 传输层
|
|
551
552
|
*/
|
|
552
553
|
export class RPCTransport {
|
|
554
|
+
rpcBudget;
|
|
553
555
|
_logger;
|
|
554
556
|
_dispatcher;
|
|
555
557
|
_serviceEventVerifier = null;
|
|
@@ -593,8 +595,15 @@ export class RPCTransport {
|
|
|
593
595
|
// Gateway 在 RPC envelope 注入 _meta 字段(与 result 同级),由 client 层 observer 接收。
|
|
594
596
|
// observer 抛异常会被吞掉,不影响 RPC result 返回。
|
|
595
597
|
_metaObserver = null;
|
|
598
|
+
_syncControlObserver = null;
|
|
599
|
+
_syncAdmission = null;
|
|
600
|
+
_syncAuxiliary = false;
|
|
601
|
+
_budgetWaiters = new Set();
|
|
596
602
|
_requestAdmission = null;
|
|
597
603
|
_requestCheck = null;
|
|
604
|
+
_standbyGate = null;
|
|
605
|
+
_businessActivity = null;
|
|
606
|
+
_standbyAuthParams = null;
|
|
598
607
|
_riskControlHandler = null;
|
|
599
608
|
_classMessageHandler = null;
|
|
600
609
|
_protocolMetaObserver = false;
|
|
@@ -626,11 +635,13 @@ export class RPCTransport {
|
|
|
626
635
|
};
|
|
627
636
|
}
|
|
628
637
|
get foregroundWaiting() {
|
|
629
|
-
return this._rpcQueue.length;
|
|
638
|
+
return this._rpcQueue.length + this.rpcBudget.foregroundWaiting;
|
|
630
639
|
}
|
|
631
640
|
_eventBackpressure(timeout = 30_000) { if (this._worker)
|
|
632
641
|
return this._workerCommand({ type: 'event_backpressure', timeout }); return Promise.resolve(this.foregroundWaiting > 0 || Number(this._ws?.bufferedAmount ?? 0) >= 65536); }
|
|
633
642
|
constructor(opts) {
|
|
643
|
+
this.rpcBudget = opts.rpcBudget ?? new RpcBudget();
|
|
644
|
+
this._syncAuxiliary = opts.syncAuxiliary ?? false;
|
|
634
645
|
this._logger = opts.logger ?? _noopLogger;
|
|
635
646
|
this._dispatcher = opts.eventDispatcher;
|
|
636
647
|
this._timeout = opts.timeout ?? 35_000;
|
|
@@ -687,6 +698,7 @@ export class RPCTransport {
|
|
|
687
698
|
aunTransportWorker: true,
|
|
688
699
|
timeout: opts.timeout ?? 35_000,
|
|
689
700
|
verifySsl: opts.verifySsl ?? true,
|
|
701
|
+
syncAuxiliary: this._syncAuxiliary,
|
|
690
702
|
},
|
|
691
703
|
});
|
|
692
704
|
this._worker = worker;
|
|
@@ -712,7 +724,7 @@ export class RPCTransport {
|
|
|
712
724
|
return;
|
|
713
725
|
}
|
|
714
726
|
if (message.type === 'foreground_drained') {
|
|
715
|
-
if (this._workerConnected && message.generation === this._workerGeneration)
|
|
727
|
+
if (this._workerConnected && message.generation === this._workerGeneration && !this.rpcBudget.foregroundWaiting)
|
|
716
728
|
this._onForegroundDrained?.();
|
|
717
729
|
return;
|
|
718
730
|
}
|
|
@@ -818,6 +830,9 @@ export class RPCTransport {
|
|
|
818
830
|
pending.reject(error);
|
|
819
831
|
}
|
|
820
832
|
this._workerPending.clear();
|
|
833
|
+
for (const request of this._budgetWaiters)
|
|
834
|
+
request.cancel?.();
|
|
835
|
+
this._budgetWaiters.clear();
|
|
821
836
|
void worker.terminate().catch(() => { });
|
|
822
837
|
if (wasConnected) {
|
|
823
838
|
this._dispatcher.enqueueProtocol('connection.error', { error });
|
|
@@ -864,6 +879,13 @@ export class RPCTransport {
|
|
|
864
879
|
}
|
|
865
880
|
if (this._workerGeneration === null || message.generation !== this._workerGeneration)
|
|
866
881
|
return;
|
|
882
|
+
if (message.event && !['_transport.disconnect', '_transport.observer', '_transport.sync_control', '_transport.rate_limit'].includes(message.event))
|
|
883
|
+
this._businessActivity?.();
|
|
884
|
+
if (message.event === '_transport.sync_control') {
|
|
885
|
+
const value = message.payload;
|
|
886
|
+
this._syncControlObserver?.(value.meta, value.method, value.params ?? {});
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
867
889
|
if (message.event === '_transport.rate_limit') {
|
|
868
890
|
const until = Number(message.payload?.until_ms);
|
|
869
891
|
if (Number.isFinite(until))
|
|
@@ -1040,6 +1062,11 @@ export class RPCTransport {
|
|
|
1040
1062
|
return this._workerConnected;
|
|
1041
1063
|
return !this._closed && this._ws !== null && this._ws.readyState === WebSocket.OPEN;
|
|
1042
1064
|
}
|
|
1065
|
+
setStandbyGate(gate, inbound = null, authentication = null) {
|
|
1066
|
+
this._standbyGate = gate;
|
|
1067
|
+
this._businessActivity = inbound;
|
|
1068
|
+
this._standbyAuthParams = authentication;
|
|
1069
|
+
}
|
|
1043
1070
|
/**
|
|
1044
1071
|
* 注册 RPC envelope _meta 字段观察者;observer(meta) 在每次成功 RPC 时调用。
|
|
1045
1072
|
*
|
|
@@ -1110,6 +1137,23 @@ export class RPCTransport {
|
|
|
1110
1137
|
this._worker.postMessage({ type: 'risk_release', generation: this._workerGeneration ?? undefined });
|
|
1111
1138
|
});
|
|
1112
1139
|
}
|
|
1140
|
+
setSyncControlObserver(observer) {
|
|
1141
|
+
this._syncControlObserver = observer;
|
|
1142
|
+
}
|
|
1143
|
+
setSyncAdmission(policy) {
|
|
1144
|
+
this._syncAdmission = policy ? { ...policy } : null;
|
|
1145
|
+
this._worker?.postMessage({ type: 'sync_admission', syncAdmission: this._syncAdmission });
|
|
1146
|
+
}
|
|
1147
|
+
_checkSyncAdmission(guard) {
|
|
1148
|
+
if (!isJsonObject(guard))
|
|
1149
|
+
return;
|
|
1150
|
+
const value = guard;
|
|
1151
|
+
const policy = this._syncAdmission;
|
|
1152
|
+
if (!policy || policy.parent_connection_id !== value.parent_connection_id || policy.version !== value.version
|
|
1153
|
+
|| Number(policy.max_history_pull_inflight) <= 0 || Number(policy.max_history_inflight_bytes) <= 0) {
|
|
1154
|
+
throw new StateError('history sync policy changed before send', { data: { sync_policy_changed: true }, retryable: true });
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1113
1157
|
setProtocolMetaObserver(observer) {
|
|
1114
1158
|
this._metaObserver = observer;
|
|
1115
1159
|
this._protocolMetaObserver = true;
|
|
@@ -1528,6 +1572,9 @@ export class RPCTransport {
|
|
|
1528
1572
|
}
|
|
1529
1573
|
/** 关闭连接 */
|
|
1530
1574
|
async close() {
|
|
1575
|
+
for (const request of this._budgetWaiters)
|
|
1576
|
+
request.cancel?.();
|
|
1577
|
+
this._budgetWaiters.clear();
|
|
1531
1578
|
if (this._worker) {
|
|
1532
1579
|
const worker = this._worker;
|
|
1533
1580
|
this._workerConnected = false;
|
|
@@ -1672,7 +1719,48 @@ export class RPCTransport {
|
|
|
1672
1719
|
const result = Promise.all([request, sent]).then(([response]) => response);
|
|
1673
1720
|
return Object.assign(result, { cancel: request.cancel });
|
|
1674
1721
|
}
|
|
1675
|
-
_call(method, params, timeout, trace, background = false, onSent, sentCheckpoint) {
|
|
1722
|
+
_call(method, params, timeout, trace, background = false, onSent, sentCheckpoint, bypassStandby = false) {
|
|
1723
|
+
if (method === 'auth.connect' && this._standbyAuthParams)
|
|
1724
|
+
params = this._standbyAuthParams(params ?? {});
|
|
1725
|
+
if (this._standbyGate && !bypassStandby && !method.startsWith('gateway.standby.')
|
|
1726
|
+
&& !['auth.aid_login1', 'auth.aid_login2', 'auth.connect'].includes(method)) {
|
|
1727
|
+
const deadline = Math.min(typeof params?._rpc_deadline === 'number' ? params._rpc_deadline : Infinity, Date.now() + (timeout ?? this._timeout));
|
|
1728
|
+
const abort = new AbortController();
|
|
1729
|
+
let active;
|
|
1730
|
+
const gate = this._standbyGate;
|
|
1731
|
+
const waiting = (async () => {
|
|
1732
|
+
const release = await gate(method, deadline, abort.signal);
|
|
1733
|
+
try {
|
|
1734
|
+
if (abort.signal.aborted || Date.now() >= deadline)
|
|
1735
|
+
throw new TimeoutError('rpc timeout during standby recovery', { retryable: true });
|
|
1736
|
+
active = this._call(method, params, deadline - Date.now(), trace, background, onSent, sentCheckpoint, true);
|
|
1737
|
+
return await active;
|
|
1738
|
+
}
|
|
1739
|
+
finally {
|
|
1740
|
+
release();
|
|
1741
|
+
}
|
|
1742
|
+
})();
|
|
1743
|
+
return Object.assign(waiting, { cancel: () => { abort.abort(); active?.cancel?.(); } });
|
|
1744
|
+
}
|
|
1745
|
+
const selected = normalizeRpcBackground(background !== false ? background : params?._rpc_background);
|
|
1746
|
+
const kind = selected === true && ['message.peers', 'message.pull', 'message.v2.pull', 'message.ack', 'message.v2.ack', 'group.pull', 'group.v2.pull', 'group.pull_events', 'group.ack_messages', 'group.v2.ack'].includes(method) ? 'pull' : selected;
|
|
1747
|
+
const deadline = Math.min(typeof params?._rpc_deadline === 'number' ? params._rpc_deadline : Infinity, Date.now() + (timeout ?? this._timeout));
|
|
1748
|
+
if (method === 'gateway.risk_ack')
|
|
1749
|
+
return this._callWithAdmission(method, params, Math.max(1, deadline - Date.now()), trace, background, onSent, sentCheckpoint);
|
|
1750
|
+
let started = false;
|
|
1751
|
+
let request;
|
|
1752
|
+
request = this.rpcBudget.run(kind, () => {
|
|
1753
|
+
started = true;
|
|
1754
|
+
this._budgetWaiters.delete(request);
|
|
1755
|
+
return this._callWithAdmission(method, params, Math.max(1, deadline - Date.now()), trace, background, onSent, sentCheckpoint);
|
|
1756
|
+
}, deadline, this._messagePriority(params?.message_class), method);
|
|
1757
|
+
if (!started) {
|
|
1758
|
+
this._budgetWaiters.add(request);
|
|
1759
|
+
void request.then(() => this._budgetWaiters.delete(request), () => this._budgetWaiters.delete(request));
|
|
1760
|
+
}
|
|
1761
|
+
return request;
|
|
1762
|
+
}
|
|
1763
|
+
_callWithAdmission(method, params, timeout, trace, background = false, onSent, sentCheckpoint) {
|
|
1676
1764
|
if (!this._requestAdmission)
|
|
1677
1765
|
return this._callAdmitted(method, params, timeout, trace, background, onSent, sentCheckpoint);
|
|
1678
1766
|
let release;
|
|
@@ -1687,6 +1775,7 @@ export class RPCTransport {
|
|
|
1687
1775
|
}
|
|
1688
1776
|
}
|
|
1689
1777
|
_callAdmitted(method, params, timeout, trace, background = false, onSent, sentCheckpoint) {
|
|
1778
|
+
this._checkSyncAdmission(params?._rpc_sync_guard);
|
|
1690
1779
|
if (this._worker) {
|
|
1691
1780
|
const requestContext = trafficLogContext('outbound', params ?? {});
|
|
1692
1781
|
const requestLog = withLogContext(this._logger, requestContext);
|
|
@@ -1726,6 +1815,10 @@ export class RPCTransport {
|
|
|
1726
1815
|
const backgroundRpc = selectedBackground === true && ['message.peers', 'message.pull', 'message.v2.pull', 'message.ack', 'message.v2.ack', 'group.pull', 'group.v2.pull', 'group.pull_events', 'group.ack_messages', 'group.v2.ack'].includes(method) ? 'pull' : selectedBackground;
|
|
1727
1816
|
delete localParams._rpc_background;
|
|
1728
1817
|
delete localParams._rpc_deadline;
|
|
1818
|
+
const sync = localParams._rpc_sync;
|
|
1819
|
+
delete localParams._rpc_sync;
|
|
1820
|
+
const syncGuard = localParams._rpc_sync_guard;
|
|
1821
|
+
delete localParams._rpc_sync_guard;
|
|
1729
1822
|
const requestContext = trafficLogContext('outbound', sendParams);
|
|
1730
1823
|
const requestLog = withLogContext(this._logger, requestContext);
|
|
1731
1824
|
const responseLog = withLogContext(requestLog, {
|
|
@@ -1746,6 +1839,7 @@ export class RPCTransport {
|
|
|
1746
1839
|
id: rpcId,
|
|
1747
1840
|
method,
|
|
1748
1841
|
params: sendParams,
|
|
1842
|
+
...(sync && typeof sync === 'object' ? { _meta: { sync } } : {}),
|
|
1749
1843
|
});
|
|
1750
1844
|
const payloadSize = new TextEncoder().encode(payload).length;
|
|
1751
1845
|
if (payloadSize > MAX_WS_PAYLOAD_SIZE) {
|
|
@@ -1829,6 +1923,7 @@ export class RPCTransport {
|
|
|
1829
1923
|
priority: this._messagePriority(localParams.message_class),
|
|
1830
1924
|
logger: requestLog,
|
|
1831
1925
|
onSent,
|
|
1926
|
+
...(isJsonObject(syncGuard) ? { syncGuard: syncGuard } : {}),
|
|
1832
1927
|
});
|
|
1833
1928
|
if (backgroundRpc) {
|
|
1834
1929
|
this._rpcQueue.pop();
|
|
@@ -1843,6 +1938,7 @@ export class RPCTransport {
|
|
|
1843
1938
|
priority: this._messagePriority(localParams.message_class),
|
|
1844
1939
|
logger: requestLog,
|
|
1845
1940
|
onSent,
|
|
1941
|
+
...(isJsonObject(syncGuard) ? { syncGuard: syncGuard } : {}),
|
|
1846
1942
|
});
|
|
1847
1943
|
}
|
|
1848
1944
|
this._drainRpcQueue();
|
|
@@ -1852,10 +1948,13 @@ export class RPCTransport {
|
|
|
1852
1948
|
/** 发送 JSON-RPC 2.0 Notification,不分配 id,也不等待响应。 */
|
|
1853
1949
|
async notify(method, params) {
|
|
1854
1950
|
const release = this._requestAdmission?.(`rpc:${String(method).replace(/^(notification|event)\//, '')}`);
|
|
1951
|
+
let standbyRelease;
|
|
1855
1952
|
try {
|
|
1953
|
+
standbyRelease = await this._standbyGate?.(method, Date.now() + this._timeout);
|
|
1856
1954
|
await this._notifyAdmitted(method, params);
|
|
1857
1955
|
}
|
|
1858
1956
|
finally {
|
|
1957
|
+
standbyRelease?.();
|
|
1859
1958
|
release?.();
|
|
1860
1959
|
}
|
|
1861
1960
|
}
|
|
@@ -1874,7 +1973,7 @@ export class RPCTransport {
|
|
|
1874
1973
|
});
|
|
1875
1974
|
}
|
|
1876
1975
|
const normalizedMethod = String(method ?? '').trim();
|
|
1877
|
-
if (!normalizedMethod.startsWith('notification/') && !normalizedMethod.startsWith('event/')) {
|
|
1976
|
+
if (!normalizedMethod.startsWith('notification/') && !normalizedMethod.startsWith('event/') && normalizedMethod !== 'gateway.sync_demand') {
|
|
1878
1977
|
throw new ValidationError('notify method must start with notification/ or event/');
|
|
1879
1978
|
}
|
|
1880
1979
|
if (params !== undefined && params !== null && !isJsonObject(params)) {
|
|
@@ -2071,7 +2170,7 @@ export class RPCTransport {
|
|
|
2071
2170
|
}
|
|
2072
2171
|
if (this._rpcQueue.length > 0) {
|
|
2073
2172
|
this._rpcQueue = this._rpcQueue.filter((entry) => entry.rpcId !== rpcId || (pending !== undefined && entry.pending !== pending));
|
|
2074
|
-
if (this.
|
|
2173
|
+
if (this.foregroundWaiting === 0 && !this._closed)
|
|
2075
2174
|
this._onForegroundDrained?.();
|
|
2076
2175
|
}
|
|
2077
2176
|
if (this._backgroundRpcQueue.length > 0) {
|
|
@@ -2150,6 +2249,7 @@ export class RPCTransport {
|
|
|
2150
2249
|
return false;
|
|
2151
2250
|
}
|
|
2152
2251
|
this._requestCheck?.(`rpc:${entry.method}`);
|
|
2252
|
+
this._checkSyncAdmission(entry.syncGuard);
|
|
2153
2253
|
entry.pending.sent = true;
|
|
2154
2254
|
return true;
|
|
2155
2255
|
}, this._isRiskControlMethod(entry.method) ? 3 : entry.priority).then(() => {
|
|
@@ -2178,7 +2278,7 @@ export class RPCTransport {
|
|
|
2178
2278
|
if (!this._closed && this._backgroundRpcQueue.length && remaining > 0) {
|
|
2179
2279
|
this._rateLimitTimer = setTimeout(() => { this._rateLimitTimer = null; this._drainRpcQueue(); }, Math.min(remaining, 2_147_483_647));
|
|
2180
2280
|
}
|
|
2181
|
-
if (foregroundDrained)
|
|
2281
|
+
if (foregroundDrained && !this.rpcBudget.foregroundWaiting)
|
|
2182
2282
|
this._onForegroundDrained?.();
|
|
2183
2283
|
}
|
|
2184
2284
|
}
|
|
@@ -2229,6 +2329,9 @@ export class RPCTransport {
|
|
|
2229
2329
|
this._stopWebSocketHeartbeat(ws);
|
|
2230
2330
|
const wasClosed = this._closed;
|
|
2231
2331
|
this._closed = true;
|
|
2332
|
+
for (const request of this._budgetWaiters)
|
|
2333
|
+
request.cancel?.();
|
|
2334
|
+
this._budgetWaiters.clear();
|
|
2232
2335
|
for (const wake of this._rateLimitWaiters)
|
|
2233
2336
|
wake();
|
|
2234
2337
|
if (this._rateLimitTimer !== null)
|
|
@@ -2272,7 +2375,8 @@ export class RPCTransport {
|
|
|
2272
2375
|
this._dispatcher.enqueueProtocol('connection.error', { error: err });
|
|
2273
2376
|
}
|
|
2274
2377
|
});
|
|
2275
|
-
this.
|
|
2378
|
+
if (!this._syncAuxiliary)
|
|
2379
|
+
this._startWebSocketHeartbeat(ws);
|
|
2276
2380
|
}
|
|
2277
2381
|
/** 使用 WebSocket 控制帧检测半开连接,不占用 JSON-RPC 并发额度。 */
|
|
2278
2382
|
_startWebSocketHeartbeat(ws) {
|
|
@@ -2365,6 +2469,19 @@ export class RPCTransport {
|
|
|
2365
2469
|
}
|
|
2366
2470
|
/** 路由消息:RPC 响应 / challenge / 事件 / 通知 */
|
|
2367
2471
|
_routeMessage(message) {
|
|
2472
|
+
if (typeof message.method === 'string' && !['meta.ping', 'system.ping', 'ping'].includes(message.method))
|
|
2473
|
+
this._businessActivity?.();
|
|
2474
|
+
const syncMethod = String(message.method ?? '');
|
|
2475
|
+
const syncMeta = isJsonObject(message._meta) ? message._meta : {};
|
|
2476
|
+
if (syncMeta.sync_policy !== undefined || syncMethod.startsWith('event/gateway.sync_')) {
|
|
2477
|
+
const policy = syncMeta.sync_policy;
|
|
2478
|
+
if (isJsonObject(policy) && this._syncAdmission?.parent_connection_id === policy.parent_connection_id
|
|
2479
|
+
&& Number.isSafeInteger(policy.version) && Number(policy.version) > Number(this._syncAdmission?.version))
|
|
2480
|
+
this._syncAdmission = { ...policy };
|
|
2481
|
+
this._syncControlObserver?.(syncMeta, syncMethod, message.params ?? {});
|
|
2482
|
+
}
|
|
2483
|
+
if (syncMethod === 'event/gateway.sync_policy_changed' || syncMethod === 'event/gateway.sync_channel_close')
|
|
2484
|
+
return;
|
|
2368
2485
|
// 入口 debug: 识别消息类型
|
|
2369
2486
|
const hasId = 'id' in message;
|
|
2370
2487
|
const methodStr = String(message.method ?? '');
|
|
@@ -2550,6 +2667,7 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
|
|
|
2550
2667
|
eventDispatcher: workerDispatcher,
|
|
2551
2668
|
timeout: Number(workerData.timeout ?? 35_000),
|
|
2552
2669
|
verifySsl: Boolean(workerData.verifySsl ?? true),
|
|
2670
|
+
syncAuxiliary: Boolean(workerData.syncAuxiliary),
|
|
2553
2671
|
// Worker 内只让 close handler 经 workerDispatcher 转发一次,主线程负责执行真实回调。
|
|
2554
2672
|
onDisconnect: () => { },
|
|
2555
2673
|
});
|
|
@@ -2562,6 +2680,7 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
|
|
|
2562
2680
|
actor._onRpcResponse = () => parentPort.postMessage({
|
|
2563
2681
|
type: 'rpc_response', generation: bridgeGeneration(),
|
|
2564
2682
|
});
|
|
2683
|
+
actor.setSyncControlObserver((meta, method, params) => parentPort.postMessage({ type: 'event', generation: actor._connectionGeneration, event: '_transport.sync_control', payload: { meta, method, params } }));
|
|
2565
2684
|
actor.setProtocolMetaObserver((meta) => workerDispatcher.enqueueProtocol('_transport.observer', {
|
|
2566
2685
|
kind: 'meta_observer', payload: meta,
|
|
2567
2686
|
}));
|
|
@@ -2596,6 +2715,9 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
|
|
|
2596
2715
|
}
|
|
2597
2716
|
let result;
|
|
2598
2717
|
switch (command.type) {
|
|
2718
|
+
case 'sync_admission':
|
|
2719
|
+
actor.setSyncAdmission(command.syncAdmission ?? null);
|
|
2720
|
+
return;
|
|
2599
2721
|
case 'risk_snapshot': {
|
|
2600
2722
|
const state = command.riskState;
|
|
2601
2723
|
const target = state.target;
|