@agentunion/fastaun 0.5.19 → 0.5.21
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 +176 -78
- package/_packed_docs/CHANGELOG.md +176 -78
- package/_packed_docs/INDEX.md +288 -269
- package/_packed_docs/KITE_DOCS_GUIDE.md +101 -95
- package/_packed_docs/agent.md/SCHEMA.md +7 -7
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/344/270/216/346/215/242owner/347/274/226/346/216/222/346/226/271/346/241/210.md +530 -0
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/345/256/214/346/225/264/350/256/276/350/256/241/344/270/216/345/256/236/346/226/275/350/256/241/345/210/222.md +685 -0
- package/_packed_docs/agent.md/working/agent.md-schema/344/270/216/347/255/276/345/217/221/351/252/214/347/255/276/346/265/201/347/250/213/346/276/204/346/270/205.md +349 -0
- package/_packed_docs/agent.md/working//346/234/254/345/234/260Docker/346/265/213/350/257/225Bug/346/270/205/345/215/225.md +40 -0
- 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 +372 -331
- package/_packed_docs/protocol/08-AUN-E2EE.md +17 -12
- 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 +445 -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 +666 -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/0.5.21-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +368 -0
- package/_packed_docs/sdk/0.5.21-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +350 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +5 -1
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +64 -64
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +70 -63
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +43 -40
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +179 -19
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +50 -49
- package/_packed_docs/sdk/09-group-rpc-manual.md +261 -254
- package/_packed_docs/sdk/09-message-rpc-manual.md +253 -160
- package/_packed_docs/sdk/09-storage-rpc-manual.md +18 -26
- package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +71 -0
- package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +88 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +105 -92
- package/_packed_docs/sdk/INDEX.md +197 -167
- 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 +930 -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 +363 -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 +553 -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 +480 -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 +63 -33
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +30 -3
- package/dist/agent-md.js +293 -152
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +42 -0
- package/dist/aid-store.js +224 -44
- 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 +78 -2
- package/dist/auth.js.map +1 -1
- package/dist/cert-utils.d.ts +44 -1
- package/dist/cert-utils.js +157 -56
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +68 -1
- package/dist/client/delivery.js +1196 -135
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +5 -1
- package/dist/client/rpc-pipeline.js +240 -111
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +12 -2
- package/dist/client/v2-e2ee.js +842 -379
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +26 -2
- package/dist/client.js +420 -75
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/events.d.ts +23 -4
- package/dist/events.js +171 -15
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +43 -1
- package/dist/facades.js +368 -12
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +7 -2
- package/dist/keystore/aid-db.js +194 -43
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/index.d.ts +15 -1
- package/dist/keystore/local-token-store.d.ts +10 -2
- package/dist/keystore/local-token-store.js +81 -16
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +45 -0
- package/dist/org-protocol.js +829 -22
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.d.ts +40 -9
- package/dist/ownership-v21.js +174 -79
- package/dist/ownership-v21.js.map +1 -1
- package/dist/ownership-workflow.d.ts +22 -0
- package/dist/ownership-workflow.js +861 -66
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/secret-store/file-store.js +84 -0
- package/dist/secret-store/file-store.js.map +1 -1
- package/dist/seq-tracker.d.ts +1 -0
- package/dist/seq-tracker.js +2 -2
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +67 -3
- package/dist/tools/cross-sdk-agent.js +575 -42
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +4 -0
- package/dist/transport.js +108 -44
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/v2/e2ee/encrypt-group.js +1 -0
- package/dist/v2/e2ee/encrypt-group.js.map +1 -1
- package/dist/v2/e2ee/encrypt-p2p.js +1 -0
- package/dist/v2/e2ee/encrypt-p2p.js.map +1 -1
- package/dist/v2/e2ee/types.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,8 @@ export declare class RpcPipeline {
|
|
|
13
13
|
private pullDrainedCheckQueued;
|
|
14
14
|
constructor(runtime: ClientRuntime);
|
|
15
15
|
call(method: string, params?: RpcParams): Promise<RpcResult>;
|
|
16
|
+
private _callWithSent;
|
|
17
|
+
private _call;
|
|
16
18
|
preflight(method: string, params?: RpcParams): RpcPreflightResult;
|
|
17
19
|
mergeInstanceProtectedHeaders(method: string, params: RpcParams): void;
|
|
18
20
|
normalizeOutboundMessagePayload(params: RpcParams, method?: string): void;
|
|
@@ -43,7 +45,8 @@ export declare class RpcPipeline {
|
|
|
43
45
|
isPullNamespaceCurrent(namespace: string): boolean;
|
|
44
46
|
invalidatePulls(): Promise<void>;
|
|
45
47
|
private pullInvalidationInProgress;
|
|
46
|
-
|
|
48
|
+
runPullNamespaceSerialized<T>(key: string, operation: () => Promise<T> | T, background?: boolean): Promise<T>;
|
|
49
|
+
runPullSerialized<T>(key: string, operation: () => Promise<T> | T, background?: boolean, namespaceOnly?: boolean): Promise<T>;
|
|
47
50
|
private executePullOperation;
|
|
48
51
|
private throwIfPullInvalidated;
|
|
49
52
|
yieldPullGate(key: string, nextKey?: string, background?: boolean): Promise<void>;
|
|
@@ -61,6 +64,7 @@ export declare class RpcPipeline {
|
|
|
61
64
|
background?: boolean;
|
|
62
65
|
pullGateKey?: string;
|
|
63
66
|
}): Promise<unknown>;
|
|
67
|
+
private observeBackgroundPullResponse;
|
|
64
68
|
private transportCallWithIdentityRecovery;
|
|
65
69
|
postprocessResult(method: string, params: RpcParams, result: unknown, options?: {
|
|
66
70
|
skipGroupState?: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto from 'node:crypto';
|
|
2
|
-
import { normalizeSlotId, slotIsolationKey } from '../config.js';
|
|
2
|
+
import { _INTERNAL_MESSAGE_FLOW_LIMITS, normalizeSlotId, slotIsolationKey } from '../config.js';
|
|
3
3
|
import { certTimeError } from '../cert-utils.js';
|
|
4
4
|
import { orgRequestParams, validateOrgRequestJSON } from '../org-protocol.js';
|
|
5
5
|
import { canonicalJson as canonicalClientRequest } from '../v2/crypto/canonical.js';
|
|
@@ -166,7 +166,14 @@ export class RpcPipeline {
|
|
|
166
166
|
this.runtime = runtime;
|
|
167
167
|
}
|
|
168
168
|
async call(method, params) {
|
|
169
|
+
return this._call(method, params);
|
|
170
|
+
}
|
|
171
|
+
async _callWithSent(method, params, onSent) {
|
|
172
|
+
return this._call(method, params, onSent);
|
|
173
|
+
}
|
|
174
|
+
async _call(method, params, onSent) {
|
|
169
175
|
const client = this.runtime.client;
|
|
176
|
+
const generation = client._delivery?.captureInlineAckGeneration?.();
|
|
170
177
|
const tStart = Date.now();
|
|
171
178
|
const requestedAckSeq = method === 'message.ack' || method === 'message.v2.ack'
|
|
172
179
|
? Number(params?.seq
|
|
@@ -192,6 +199,23 @@ export class RpcPipeline {
|
|
|
192
199
|
const deferGroupReadyPostprocess = Boolean(p._defer_group_ready_postprocess);
|
|
193
200
|
delete p._defer_group_ready_postprocess;
|
|
194
201
|
const pullGateKey = this.pullGateKeyForCall(method, p);
|
|
202
|
+
if (client._p2pPeerPullEnabled && method === 'message.peers')
|
|
203
|
+
return await client._delivery.peers(p, rpcBackground);
|
|
204
|
+
if (client._p2pPeerPullEnabled && (method === 'message.pull' || method === 'message.v2.pull')) {
|
|
205
|
+
await client._ensureV2SessionReady('message.pull');
|
|
206
|
+
return await client._delivery.pullPeers(p, rpcBackground);
|
|
207
|
+
}
|
|
208
|
+
if (client._p2pPeerPullEnabled && method === 'message.history') {
|
|
209
|
+
await client._ensureV2SessionReady('message.history');
|
|
210
|
+
const key = this.pullGateKeyForCall(method, p);
|
|
211
|
+
return await this.runPullNamespaceSerialized(key, () => client._v2E2EE.peerHistoryV2(p), rpcBackground);
|
|
212
|
+
}
|
|
213
|
+
if (client._p2pPeerPullEnabled && (method === 'message.ack' || method === 'message.v2.ack')) {
|
|
214
|
+
const sender = String(p.sender_aid ?? '').trim();
|
|
215
|
+
if (!sender)
|
|
216
|
+
throw new ValidationError('peer ACK requires sender_aid');
|
|
217
|
+
return await client._v2E2EE.ackPeerV2(sender, requestedAckSeq || undefined, Array.isArray(p.volatile_cursors) ? p.volatile_cursors : [], Array.isArray(p.volatile_ids) ? p.volatile_ids : []);
|
|
218
|
+
}
|
|
195
219
|
const runWithPullResponseScope = async (operation) => {
|
|
196
220
|
const scope = pullGateNamespace || (pullGateKey ? this.pullScopeKey(pullGateKey) : '');
|
|
197
221
|
const wrapper = client._withPullResponseProcessing;
|
|
@@ -205,9 +229,13 @@ export class RpcPipeline {
|
|
|
205
229
|
lockedParams._pull_gate_namespace = this.pullScopeKey(pullGateKey);
|
|
206
230
|
if (pullBackground)
|
|
207
231
|
lockedParams._rpc_background = true;
|
|
232
|
+
else
|
|
233
|
+
lockedParams._rpc_foreground = true;
|
|
208
234
|
if (skipSendResultEnvelope)
|
|
209
235
|
lockedParams._skip_send_result_envelope = true;
|
|
210
|
-
|
|
236
|
+
const run = ['group.pull', 'group.v2.pull', 'group.history'].includes(method)
|
|
237
|
+
? this.runPullNamespaceSerialized.bind(this) : this.runPullSerialized.bind(this);
|
|
238
|
+
return await run(pullGateKey, async () => this.call(method, lockedParams), pullBackground);
|
|
211
239
|
}
|
|
212
240
|
if (method === 'message.send') {
|
|
213
241
|
const encrypt = p.encrypt ?? true;
|
|
@@ -220,6 +248,7 @@ export class RpcPipeline {
|
|
|
220
248
|
ttl: p.ttl,
|
|
221
249
|
protectedHeaders: client._protectedHeadersFromParams(p),
|
|
222
250
|
context: isJsonObject(p.context) ? p.context : undefined,
|
|
251
|
+
needRender: p.need_render,
|
|
223
252
|
}));
|
|
224
253
|
}
|
|
225
254
|
client._maybeAppendEchoTraceSend(p);
|
|
@@ -234,6 +263,7 @@ export class RpcPipeline {
|
|
|
234
263
|
timestamp: p.timestamp,
|
|
235
264
|
protectedHeaders: client._protectedHeadersFromParams(p),
|
|
236
265
|
context: isJsonObject(p.context) ? p.context : undefined,
|
|
266
|
+
needRender: p.need_render,
|
|
237
267
|
}));
|
|
238
268
|
}
|
|
239
269
|
client._maybeAppendEchoTraceSend(p);
|
|
@@ -296,12 +326,12 @@ export class RpcPipeline {
|
|
|
296
326
|
}
|
|
297
327
|
await client._ensureV2SessionReady('group.pull');
|
|
298
328
|
if (p.window_mode === 'tail') {
|
|
299
|
-
return await runWithPullResponseScope(() => client._v2E2EE.pullGroupV2TailInternal(p));
|
|
329
|
+
return await runWithPullResponseScope(() => client._v2E2EE.pullGroupV2TailInternal(p, false, true));
|
|
300
330
|
}
|
|
301
331
|
const hasExplicitAfterSeq = 'after_seq' in p || 'after_message_seq' in p;
|
|
302
332
|
const cursorParams = this.explicitGroupCursorParams(p);
|
|
303
333
|
const ownsCursor = Object.keys(cursorParams).length === 0 || this.groupCursorTargetsCurrentInstance(cursorParams);
|
|
304
|
-
const pullOpts = { gateLocked: true };
|
|
334
|
+
const pullOpts = { gateLocked: true, background: rpcBackground };
|
|
305
335
|
if (hasExplicitAfterSeq)
|
|
306
336
|
pullOpts.explicitAfterSeq = true;
|
|
307
337
|
if (p.force === true)
|
|
@@ -314,7 +344,7 @@ export class RpcPipeline {
|
|
|
314
344
|
pullOpts.wireGroupId = String(p.group_id).trim();
|
|
315
345
|
if (String(p.group_aid ?? '').trim())
|
|
316
346
|
pullOpts.groupAid = String(p.group_aid).trim();
|
|
317
|
-
const messages = await runWithPullResponseScope(() =>
|
|
347
|
+
const messages = await runWithPullResponseScope(() => client._pullGroupV2(String(p.group_id ?? p.group_aid), Number(p.after_seq ?? p.after_message_seq ?? 0) || 0, Number(p.limit ?? 50) || 50, pullOpts));
|
|
318
348
|
return { messages };
|
|
319
349
|
}
|
|
320
350
|
if (method === 'group.history') {
|
|
@@ -347,16 +377,21 @@ export class RpcPipeline {
|
|
|
347
377
|
client._clientLog.debug(`thought.get transport call start: method=${method}, params=${client._debugJson(client._messageEnvelopeFieldsForDebug(p))}`);
|
|
348
378
|
}
|
|
349
379
|
const invokeTransport = () => {
|
|
350
|
-
const request =
|
|
351
|
-
? (rpcBackground
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
:
|
|
380
|
+
const request = onSent
|
|
381
|
+
? client._transport['_callWithSent'](method, p, onSent, callTimeout, undefined, rpcBackground)
|
|
382
|
+
: callTimeout
|
|
383
|
+
? (rpcBackground
|
|
384
|
+
? client._transport.call(method, p, callTimeout, undefined, true)
|
|
385
|
+
: client._transport.call(method, p, callTimeout))
|
|
386
|
+
: (rpcBackground
|
|
387
|
+
? client._transport.call(method, p, undefined, undefined, true)
|
|
388
|
+
: client._transport.call(method, p));
|
|
357
389
|
return this.bindActivePullCancellation(method, p, request);
|
|
358
390
|
};
|
|
359
391
|
let result = await this.transportCallWithIdentityRecovery(invokeTransport, method, p);
|
|
392
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.()) {
|
|
393
|
+
this.observeBackgroundPullResponse(method, p, result, pullGateNamespace);
|
|
394
|
+
}
|
|
360
395
|
const sendResultModeSource = result;
|
|
361
396
|
result = await this.postprocessResult(method, p, result, {
|
|
362
397
|
skipGroupState: deferGroupReadyPostprocess,
|
|
@@ -372,6 +407,10 @@ export class RpcPipeline {
|
|
|
372
407
|
client._clientLog.debug(`call exit (error): method=${method} elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
|
|
373
408
|
throw err;
|
|
374
409
|
}
|
|
410
|
+
finally {
|
|
411
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.())
|
|
412
|
+
client._delivery?.requestBackgroundPullRecovery?.();
|
|
413
|
+
}
|
|
375
414
|
}
|
|
376
415
|
preflight(method, params) {
|
|
377
416
|
const client = this.runtime.client;
|
|
@@ -383,8 +422,11 @@ export class RpcPipeline {
|
|
|
383
422
|
}
|
|
384
423
|
const p = { ...(params ?? {}) };
|
|
385
424
|
this.mergeInstanceProtectedHeaders(method, p);
|
|
386
|
-
const rpcBackground = Boolean(p.
|
|
425
|
+
const rpcBackground = !Boolean(p._rpc_foreground)
|
|
426
|
+
&& (Boolean(p._rpc_background)
|
|
427
|
+
|| (!['message.peers', 'message.pull', 'message.v2.pull', 'group.pull', 'group.v2.pull', 'group.history', 'group.pull_events'].includes(method) && client._backgroundRpcDepth > 0));
|
|
387
428
|
delete p._rpc_background;
|
|
429
|
+
delete p._rpc_foreground;
|
|
388
430
|
if (method === 'message.send' || method === 'group.send') {
|
|
389
431
|
this.normalizeOutboundMessagePayload(p, method);
|
|
390
432
|
const messageId = String(p.message_id ?? '').trim();
|
|
@@ -421,6 +463,9 @@ export class RpcPipeline {
|
|
|
421
463
|
}
|
|
422
464
|
}
|
|
423
465
|
validateOutboundCall(method, params) {
|
|
466
|
+
if ((method === 'message.send' || method === 'group.send') && params.need_render !== undefined && typeof params.need_render !== 'boolean') {
|
|
467
|
+
throw new ValidationError('need_render must be a boolean');
|
|
468
|
+
}
|
|
424
469
|
if (method === 'message.send') {
|
|
425
470
|
this.validateMessageRecipient(params.to);
|
|
426
471
|
// 校验目标 AID 格式(拒绝 __system__ 等非法格式)
|
|
@@ -483,7 +528,7 @@ export class RpcPipeline {
|
|
|
483
528
|
}
|
|
484
529
|
}
|
|
485
530
|
injectMessageCursorContext(method, params) {
|
|
486
|
-
if (!['message.pull', 'message.v2.pull', 'message.ack', 'message.v2.ack'].includes(method)) {
|
|
531
|
+
if (!['message.pull', 'message.v2.pull', 'message.history', 'message.ack', 'message.v2.ack', 'message.peers'].includes(method)) {
|
|
487
532
|
return;
|
|
488
533
|
}
|
|
489
534
|
const client = this.runtime.client;
|
|
@@ -496,6 +541,19 @@ export class RpcPipeline {
|
|
|
496
541
|
}
|
|
497
542
|
params.device_id = client._deviceId;
|
|
498
543
|
params.slot_id = client._slotId;
|
|
544
|
+
if (client._p2pPeerPullEnabled) {
|
|
545
|
+
if (params.cursor_scope !== undefined && params.cursor_scope !== 'peer')
|
|
546
|
+
throw new ValidationError('new SDK requires peer cursor_scope');
|
|
547
|
+
if (params.sender_aid !== undefined)
|
|
548
|
+
validateAIDFormat(params.sender_aid, 'sender_aid');
|
|
549
|
+
params.cursor_scope = 'peer';
|
|
550
|
+
if ((method === 'message.pull' || method === 'message.v2.pull') && params.sender_aid && !('after_volatile_cursor' in params)) {
|
|
551
|
+
const cursor = client._delivery.peerVolatilePullCursor(String(params.sender_aid));
|
|
552
|
+
if (cursor)
|
|
553
|
+
params.after_volatile_cursor = cursor;
|
|
554
|
+
}
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
499
557
|
if ((method === 'message.pull' || method === 'message.v2.pull') && !('after_volatile_cursor' in params)) {
|
|
500
558
|
const cursor = String(client._delivery.volatilePullCursor?.() ?? '').trim();
|
|
501
559
|
if (cursor)
|
|
@@ -555,6 +613,12 @@ export class RpcPipeline {
|
|
|
555
613
|
validateOrgRequestJSON(paramsForHash);
|
|
556
614
|
const paramsJson = method.startsWith('org.') ? new TextDecoder().decode(canonicalClientRequest(paramsForHash)) : stableStringify(paramsForHash);
|
|
557
615
|
const paramsHash = crypto.createHash('sha256').update(paramsJson, 'utf-8').digest('hex');
|
|
616
|
+
if (params.client_signature !== undefined) {
|
|
617
|
+
const existing = params.client_signature;
|
|
618
|
+
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')))
|
|
619
|
+
throw new Error('已有客户端签名与请求内容不一致');
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
558
622
|
const signData = Buffer.from(`${method}|${aid}|${ts}|${paramsHash}`, 'utf-8');
|
|
559
623
|
const privateKey = getSigningPrivateKey(currentAid.privateKeyPem);
|
|
560
624
|
const signature = crypto.sign('SHA256', signData, privateKey);
|
|
@@ -595,7 +659,10 @@ export class RpcPipeline {
|
|
|
595
659
|
cursor = `after=${String(params.after_seq ?? 0)}`;
|
|
596
660
|
}
|
|
597
661
|
const limit = mode === 'forward' ? (Number(params.limit ?? 50) || 50) : params.limit;
|
|
598
|
-
|
|
662
|
+
if (client._p2pPeerPullEnabled && !params.sender_aid)
|
|
663
|
+
return '';
|
|
664
|
+
const namespace = client._p2pPeerPullEnabled ? client._delivery.peerNamespace(String(params.sender_aid)) : `p2p:${client._aid}`;
|
|
665
|
+
return `${namespace}|mode=${mode}|cursor=${cursor}|volatile=${String(params.after_volatile_cursor ?? '')}|force=${String(Boolean(params.force))}|limit=${String(limit)}`;
|
|
599
666
|
}
|
|
600
667
|
if (method === 'group.pull' || method === 'group.v2.pull' || method === 'group.history') {
|
|
601
668
|
const groupId = String(params.group_id ?? params.group_aid ?? '').trim();
|
|
@@ -640,14 +707,15 @@ export class RpcPipeline {
|
|
|
640
707
|
void key;
|
|
641
708
|
return 'pull';
|
|
642
709
|
}
|
|
643
|
-
pullGateState(key) {
|
|
644
|
-
const name = this.pullGateName(key);
|
|
710
|
+
pullGateState(key, namespaceOnly = false) {
|
|
711
|
+
const name = namespaceOnly ? 'pull-namespace' : this.pullGateName(key);
|
|
645
712
|
let state = this.pullGateStates.get(name);
|
|
646
713
|
if (!state) {
|
|
647
|
-
state = {
|
|
714
|
+
state = { networkLimited: !namespaceOnly, activeByNamespace: new Map(), foreground: [], background: [], backgroundPeerDispatches: 0, byKey: new Map(), lifecycle: new Map(), watchdog: null };
|
|
648
715
|
this.pullGateStates.set(name, state);
|
|
649
716
|
}
|
|
650
|
-
|
|
717
|
+
if (state.networkLimited)
|
|
718
|
+
this.startPullGateWatchdog(state, name);
|
|
651
719
|
return state;
|
|
652
720
|
}
|
|
653
721
|
pullGateOperationTimeoutMs() {
|
|
@@ -675,23 +743,25 @@ export class RpcPipeline {
|
|
|
675
743
|
}
|
|
676
744
|
}
|
|
677
745
|
checkPullGate(state, name) {
|
|
678
|
-
const
|
|
679
|
-
if (
|
|
746
|
+
const activeJobs = [...state.activeByNamespace.values()];
|
|
747
|
+
if (activeJobs.length === 0) {
|
|
680
748
|
this.drainPullGate(state);
|
|
681
749
|
return;
|
|
682
750
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
751
|
+
for (const active of activeJobs) {
|
|
752
|
+
if (!active.pullingStartedAt || Date.now() - active.pullingStartedAt < this.pullGateOperationTimeoutMs())
|
|
753
|
+
continue;
|
|
754
|
+
if (active.timedOut)
|
|
755
|
+
continue;
|
|
756
|
+
active.timedOut = true;
|
|
757
|
+
active.invalidated = true;
|
|
758
|
+
active.cancel?.();
|
|
759
|
+
const timeout = new TimeoutError(`pull gate timeout: ${active.namespace}`, { retryable: true });
|
|
760
|
+
this.runtime.client._clientLog.warn(`pull gate watchdog timeout: gate=${name} key=${active.key} elapsed=${Date.now() - active.pullingStartedAt}ms`);
|
|
761
|
+
// 仅拒绝当前调用方;取消不敏感的 operation 仍可能运行,必须等其
|
|
762
|
+
// 真正 settle 后才释放 active,避免与后续 Pull 并发修改游标。
|
|
763
|
+
active.reject(timeout);
|
|
764
|
+
}
|
|
695
765
|
}
|
|
696
766
|
pullScopeKey(key) {
|
|
697
767
|
return key.split('|', 1)[0] ?? key;
|
|
@@ -706,7 +776,7 @@ export class RpcPipeline {
|
|
|
706
776
|
if (typeof cancel !== 'function' || !key)
|
|
707
777
|
return request;
|
|
708
778
|
const state = this.pullGateStates.get(this.pullGateName(key));
|
|
709
|
-
const active = state?.
|
|
779
|
+
const active = [...(state?.activeByNamespace.values() ?? [])].find((candidate) => candidate.key === key);
|
|
710
780
|
if (!active || active.key !== key || active.timedOut || active.invalidated)
|
|
711
781
|
return request;
|
|
712
782
|
const boundCancel = () => cancel.call(request);
|
|
@@ -723,9 +793,11 @@ export class RpcPipeline {
|
|
|
723
793
|
}
|
|
724
794
|
hasPullActivity(namespace, includePending = true) {
|
|
725
795
|
const ns = String(namespace ?? '').trim();
|
|
726
|
-
if ((!ns.startsWith('p2p:') && !ns.startsWith('group:')) || this.hasInlineRealtimeGuard(ns))
|
|
796
|
+
if ((!ns.startsWith('p2p:') && !ns.startsWith('p2p.peer.v1/') && !ns.startsWith('group:')) || this.hasInlineRealtimeGuard(ns))
|
|
727
797
|
return true;
|
|
728
798
|
const client = this.runtime.client;
|
|
799
|
+
if (client._delivery?.hasPeerPageActivity?.(ns))
|
|
800
|
+
return true;
|
|
729
801
|
if ((client._pullResponseKeys.get(ns) ?? 0) > 0)
|
|
730
802
|
return true;
|
|
731
803
|
if (includePending && Number(client._pendingP2pPullUpper?.get?.(ns) ?? 0) > 0)
|
|
@@ -744,15 +816,15 @@ export class RpcPipeline {
|
|
|
744
816
|
return true;
|
|
745
817
|
}
|
|
746
818
|
for (const state of this.pullGateStates.values()) {
|
|
747
|
-
const jobs = [state.
|
|
748
|
-
if (jobs.some((job) =>
|
|
819
|
+
const jobs = [...state.activeByNamespace.values(), ...state.foreground, ...state.background];
|
|
820
|
+
if (jobs.some((job) => this.pullScopeKey(job.key) === ns))
|
|
749
821
|
return true;
|
|
750
822
|
}
|
|
751
823
|
return false;
|
|
752
824
|
}
|
|
753
825
|
async tryRunInlineRealtime(namespace, seq, operation) {
|
|
754
826
|
const ns = String(namespace ?? '').trim();
|
|
755
|
-
if ((!ns.startsWith('p2p:') && !ns.startsWith('group:'))
|
|
827
|
+
if ((!ns.startsWith('p2p:') && !ns.startsWith('p2p.peer.v1/') && !ns.startsWith('group:'))
|
|
756
828
|
|| !Number.isSafeInteger(seq) || seq <= 0 || typeof operation !== 'function'
|
|
757
829
|
|| this.hasPullActivity(ns)) {
|
|
758
830
|
return { acquired: false };
|
|
@@ -763,12 +835,11 @@ export class RpcPipeline {
|
|
|
763
835
|
}
|
|
764
836
|
finally {
|
|
765
837
|
this.inlineRealtimeScopes.delete(ns);
|
|
766
|
-
const state
|
|
767
|
-
if (state) {
|
|
838
|
+
for (const state of this.pullGateStates.values()) {
|
|
768
839
|
this.drainPullGate(state);
|
|
769
|
-
this.runtime.client._delivery?.onPullGateIdle?.(ns);
|
|
770
840
|
this.armQueuedPullTimers(state);
|
|
771
841
|
}
|
|
842
|
+
this.runtime.client._delivery?.onPullGateIdle?.(ns);
|
|
772
843
|
}
|
|
773
844
|
}
|
|
774
845
|
tryAcquirePullGate(key) {
|
|
@@ -808,8 +879,10 @@ export class RpcPipeline {
|
|
|
808
879
|
const ns = this.pullScopeKey(namespace);
|
|
809
880
|
if (!ns)
|
|
810
881
|
return true;
|
|
811
|
-
|
|
812
|
-
|
|
882
|
+
return [...this.pullGateStates.values()].every((state) => {
|
|
883
|
+
const active = state.activeByNamespace.get(ns);
|
|
884
|
+
return !active || active.namespace !== ns || (!active.timedOut && !active.invalidated);
|
|
885
|
+
});
|
|
813
886
|
}
|
|
814
887
|
invalidatePulls() {
|
|
815
888
|
if (this.pullInvalidationWait)
|
|
@@ -819,8 +892,8 @@ export class RpcPipeline {
|
|
|
819
892
|
const waits = [];
|
|
820
893
|
for (const state of this.pullGateStates.values()) {
|
|
821
894
|
const jobs = new Set();
|
|
822
|
-
|
|
823
|
-
jobs.add(
|
|
895
|
+
for (const active of state.activeByNamespace.values())
|
|
896
|
+
jobs.add(active);
|
|
824
897
|
for (const job of state.foreground)
|
|
825
898
|
jobs.add(job);
|
|
826
899
|
for (const job of state.background)
|
|
@@ -842,6 +915,7 @@ export class RpcPipeline {
|
|
|
842
915
|
}
|
|
843
916
|
state.foreground = state.foreground.filter((job) => !jobs.has(job));
|
|
844
917
|
state.background = state.background.filter((job) => !jobs.has(job));
|
|
918
|
+
state.backgroundPeerDispatches = 0;
|
|
845
919
|
for (const [key, job] of state.byKey.entries()) {
|
|
846
920
|
if (jobs.has(job) && !job.running)
|
|
847
921
|
state.byKey.delete(key);
|
|
@@ -860,7 +934,10 @@ export class RpcPipeline {
|
|
|
860
934
|
pullInvalidationInProgress() {
|
|
861
935
|
return this.pullInvalidationWait !== null;
|
|
862
936
|
}
|
|
863
|
-
async
|
|
937
|
+
async runPullNamespaceSerialized(key, operation, background = false) {
|
|
938
|
+
return await this.runPullSerialized(key, operation, background, true);
|
|
939
|
+
}
|
|
940
|
+
async runPullSerialized(key, operation, background = false, namespaceOnly = false) {
|
|
864
941
|
if (this.runtime.client._dispatcher?._isApplicationHandler?.()) {
|
|
865
942
|
throw new Error('pull cannot wait inside an application handler');
|
|
866
943
|
}
|
|
@@ -876,9 +953,9 @@ export class RpcPipeline {
|
|
|
876
953
|
throw error;
|
|
877
954
|
}
|
|
878
955
|
}
|
|
879
|
-
const state = this.pullGateState(key);
|
|
956
|
+
const state = this.pullGateState(key, namespaceOnly);
|
|
880
957
|
const namespace = this.pullScopeKey(key);
|
|
881
|
-
const active = state.
|
|
958
|
+
const active = [...state.activeByNamespace.values()].find((job) => job.key === key && !job.timedOut && !job.invalidated) ?? null;
|
|
882
959
|
const queuedForeground = state.foreground.find((job) => job.key === key && !job.timedOut && !job.invalidated);
|
|
883
960
|
const queuedBackground = state.background.find((job) => job.key === key && !job.timedOut && !job.invalidated);
|
|
884
961
|
const existing = background
|
|
@@ -920,7 +997,8 @@ export class RpcPipeline {
|
|
|
920
997
|
queue.push(job);
|
|
921
998
|
state.byKey.set(key, job);
|
|
922
999
|
this.drainPullGate(state);
|
|
923
|
-
|
|
1000
|
+
if (state.networkLimited)
|
|
1001
|
+
this.checkPullGate(state, this.pullGateName(key));
|
|
924
1002
|
return await promise;
|
|
925
1003
|
}
|
|
926
1004
|
async executePullOperation(operation, background) {
|
|
@@ -938,8 +1016,8 @@ export class RpcPipeline {
|
|
|
938
1016
|
return;
|
|
939
1017
|
const state = this.pullGateState(key);
|
|
940
1018
|
const namespace = this.pullScopeKey(key);
|
|
941
|
-
const job = state.
|
|
942
|
-
if (!job ||
|
|
1019
|
+
const job = [...state.activeByNamespace.values()].find((candidate) => candidate.key === key) ?? null;
|
|
1020
|
+
if (!job || job.timedOut || job.invalidated)
|
|
943
1021
|
return;
|
|
944
1022
|
const replacementKey = String(nextKey || key);
|
|
945
1023
|
if (state.byKey.get(job.key) === job)
|
|
@@ -958,7 +1036,7 @@ export class RpcPipeline {
|
|
|
958
1036
|
state.lifecycle.set(namespace, 'pulled');
|
|
959
1037
|
job.suspended = true;
|
|
960
1038
|
job.resume = new Promise((resolve) => { job.resumeResolve = resolve; });
|
|
961
|
-
state.
|
|
1039
|
+
state.activeByNamespace.delete(namespace);
|
|
962
1040
|
(job.background ? state.background : state.foreground).push(job);
|
|
963
1041
|
this.drainPullGate(state);
|
|
964
1042
|
if (job.resume) {
|
|
@@ -978,67 +1056,93 @@ export class RpcPipeline {
|
|
|
978
1056
|
if (!ns)
|
|
979
1057
|
return;
|
|
980
1058
|
const state = this.pullGateStates.get(this.pullGateName(ns));
|
|
981
|
-
if (!state || state.
|
|
1059
|
+
if (!state || !state.activeByNamespace.has(ns))
|
|
982
1060
|
return;
|
|
983
1061
|
state.lifecycle.set(ns, lifecycle);
|
|
984
1062
|
}
|
|
985
1063
|
drainPullGate(state) {
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
const
|
|
989
|
-
|
|
990
|
-
|
|
1064
|
+
const peerForward = (job) => job.background && job.namespace.startsWith('p2p.peer.v1/')
|
|
1065
|
+
&& job.key.includes('|mode=forward|') && !job.key.includes('|force=true|');
|
|
1066
|
+
const priority = (job) => peerForward(job)
|
|
1067
|
+
? this.runtime.client._delivery?.peerPullPriority?.(job.namespace) ?? null : null;
|
|
1068
|
+
const runnable = (candidate) => (!this.hasInlineRealtimeGuard(this.pullScopeKey(candidate.key))
|
|
1069
|
+
&& !state.activeByNamespace.has(candidate.namespace));
|
|
1070
|
+
const takeRunnable = (queue, background = false) => {
|
|
1071
|
+
let index = queue.findIndex(runnable);
|
|
1072
|
+
if (index < 0)
|
|
1073
|
+
return;
|
|
1074
|
+
if (background && peerForward(queue[index])
|
|
1075
|
+
&& (state.backgroundPeerDispatches + 1) % _INTERNAL_MESSAGE_FLOW_LIMITS.pullMaxInflight !== 0) {
|
|
1076
|
+
let best = priority(queue[index]);
|
|
1077
|
+
if (best !== null) {
|
|
1078
|
+
for (let next = index + 1; next < queue.length; next += 1) {
|
|
1079
|
+
const hint = priority(queue[next]);
|
|
1080
|
+
if (hint === null)
|
|
1081
|
+
break;
|
|
1082
|
+
if (runnable(queue[next]) && hint < best) {
|
|
1083
|
+
best = hint;
|
|
1084
|
+
index = next;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
const job = queue.splice(index, 1)[0];
|
|
1090
|
+
if (background && peerForward(job))
|
|
1091
|
+
state.backgroundPeerDispatches += 1;
|
|
1092
|
+
return job;
|
|
991
1093
|
};
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
job.pullingStartedAt = Date.now();
|
|
1006
|
-
job.timedOut = false;
|
|
1007
|
-
state.lifecycle.set(job.namespace, 'pulling');
|
|
1008
|
-
const resumeResolve = job.resumeResolve;
|
|
1009
|
-
job.resume = null;
|
|
1010
|
-
job.resumeResolve = null;
|
|
1011
|
-
if (job.suspended) {
|
|
1012
|
-
job.suspended = false;
|
|
1013
|
-
resumeResolve?.();
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
job.running = true;
|
|
1017
|
-
const operationPromise = this.executePullOperation(job.operation, job.background);
|
|
1018
|
-
let failed = false;
|
|
1019
|
-
void operationPromise
|
|
1020
|
-
.then((value) => { if (!job.timedOut && !job.invalidated)
|
|
1021
|
-
job.resolve(value); }, (error) => {
|
|
1022
|
-
failed = true;
|
|
1023
|
-
if (!job.timedOut && !job.invalidated)
|
|
1024
|
-
job.reject(error);
|
|
1025
|
-
})
|
|
1026
|
-
.finally(() => {
|
|
1027
|
-
state.lifecycle.set(job.namespace, 'idle');
|
|
1028
|
-
if (state.active === job)
|
|
1029
|
-
state.active = null;
|
|
1030
|
-
if (state.byKey.get(job.key) === job)
|
|
1031
|
-
state.byKey.delete(job.key);
|
|
1032
|
-
this.drainPullGate(state);
|
|
1033
|
-
job.settledResolve?.();
|
|
1034
|
-
job.settledResolve = null;
|
|
1035
|
-
if (!job.invalidated) {
|
|
1036
|
-
this.runtime.client._delivery?.onPullGateIdle?.(job.namespace);
|
|
1094
|
+
while (state.activeByNamespace.size < _INTERNAL_MESSAGE_FLOW_LIMITS.pullMaxInflight) {
|
|
1095
|
+
const foregroundJob = takeRunnable(state.foreground);
|
|
1096
|
+
const foregroundDrained = foregroundJob !== undefined && state.foreground.length === 0;
|
|
1097
|
+
const job = foregroundJob ?? takeRunnable(state.background, true);
|
|
1098
|
+
if (!job)
|
|
1099
|
+
break;
|
|
1100
|
+
state.activeByNamespace.set(job.namespace, job);
|
|
1101
|
+
this.runtime.client._delivery?.syncStarted?.(job.namespace);
|
|
1102
|
+
if (foregroundDrained)
|
|
1103
|
+
this.runtime.client._delivery?.onForegroundPullsDrained?.();
|
|
1104
|
+
if (job.timer) {
|
|
1105
|
+
clearTimeout(job.timer);
|
|
1106
|
+
job.timer = null;
|
|
1037
1107
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1108
|
+
job.pullingStartedAt = Date.now();
|
|
1109
|
+
job.timedOut = false;
|
|
1110
|
+
state.lifecycle.set(job.namespace, 'pulling');
|
|
1111
|
+
const resumeResolve = job.resumeResolve;
|
|
1112
|
+
job.resume = null;
|
|
1113
|
+
job.resumeResolve = null;
|
|
1114
|
+
if (job.suspended) {
|
|
1115
|
+
job.suspended = false;
|
|
1116
|
+
resumeResolve?.();
|
|
1117
|
+
continue;
|
|
1118
|
+
}
|
|
1119
|
+
job.running = true;
|
|
1120
|
+
const operationPromise = this.executePullOperation(job.operation, state.networkLimited && job.background);
|
|
1121
|
+
let failed = false;
|
|
1122
|
+
void operationPromise
|
|
1123
|
+
.then((value) => { if (!job.timedOut && !job.invalidated)
|
|
1124
|
+
job.resolve(value); }, (error) => {
|
|
1125
|
+
failed = true;
|
|
1126
|
+
if (!job.timedOut && !job.invalidated)
|
|
1127
|
+
job.reject(error);
|
|
1128
|
+
})
|
|
1129
|
+
.finally(() => {
|
|
1130
|
+
state.lifecycle.set(job.namespace, 'idle');
|
|
1131
|
+
if (state.activeByNamespace.get(job.namespace) === job)
|
|
1132
|
+
state.activeByNamespace.delete(job.namespace);
|
|
1133
|
+
if (state.byKey.get(job.key) === job)
|
|
1134
|
+
state.byKey.delete(job.key);
|
|
1135
|
+
this.drainPullGate(state);
|
|
1136
|
+
job.settledResolve?.();
|
|
1137
|
+
job.settledResolve = null;
|
|
1138
|
+
if (!job.invalidated) {
|
|
1139
|
+
this.runtime.client._delivery?.onPullGateIdle?.(job.namespace);
|
|
1140
|
+
}
|
|
1141
|
+
if (failed || job.invalidated)
|
|
1142
|
+
this.runtime.client._delivery?.onPullAborted?.();
|
|
1143
|
+
this.notifyPullDrainedIfIdle();
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1042
1146
|
}
|
|
1043
1147
|
notifyPullDrainedIfIdle() {
|
|
1044
1148
|
if (this.pullDrainedCheckQueued)
|
|
@@ -1054,7 +1158,7 @@ export class RpcPipeline {
|
|
|
1054
1158
|
}
|
|
1055
1159
|
notifyPullDrainedIfIdleStable() {
|
|
1056
1160
|
for (const state of this.pullGateStates.values()) {
|
|
1057
|
-
if (state.
|
|
1161
|
+
if (state.activeByNamespace.size > 0 || state.foreground.length > 0 || state.background.length > 0)
|
|
1058
1162
|
return;
|
|
1059
1163
|
}
|
|
1060
1164
|
const client = this.runtime.client;
|
|
@@ -1087,9 +1191,34 @@ export class RpcPipeline {
|
|
|
1087
1191
|
request = client._transport.call(method, payload);
|
|
1088
1192
|
return this.bindActivePullCancellation(method, payload, request, pullGateKey);
|
|
1089
1193
|
};
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1194
|
+
const generation = client._delivery?.captureInlineAckGeneration?.();
|
|
1195
|
+
try {
|
|
1196
|
+
const result = await this.transportCallWithIdentityRecovery(invokeTransport, method, payload);
|
|
1197
|
+
this.throwIfPullInvalidated(this.pullScopeKey(pullGateKey || this.pullGateKeyForCall(method, payload)));
|
|
1198
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.()) {
|
|
1199
|
+
this.observeBackgroundPullResponse(method, payload, result, pullGateKey);
|
|
1200
|
+
}
|
|
1201
|
+
return result;
|
|
1202
|
+
}
|
|
1203
|
+
finally {
|
|
1204
|
+
if (generation === client._delivery?.captureInlineAckGeneration?.())
|
|
1205
|
+
client._delivery?.requestBackgroundPullRecovery?.();
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
observeBackgroundPullResponse(method, params, result, key = '') {
|
|
1209
|
+
if (!['message.pull', 'message.v2.pull', 'group.pull', 'group.v2.pull', 'group.pull_events'].includes(method)
|
|
1210
|
+
|| params.force === true || params.window_mode === 'tail')
|
|
1211
|
+
return;
|
|
1212
|
+
const client = this.runtime.client;
|
|
1213
|
+
if (method.startsWith('group.') && !this.groupCursorTargetsCurrentInstance(params))
|
|
1214
|
+
return;
|
|
1215
|
+
const explicitCursor = this.explicitGroupCursorParams(params);
|
|
1216
|
+
if (method.startsWith('group.') && !this.groupCursorTargetsCurrentInstance(explicitCursor))
|
|
1217
|
+
return;
|
|
1218
|
+
const ns = this.pullScopeKey(key) || (method === 'group.pull_events'
|
|
1219
|
+
? `group_event:${String(params.group_id ?? params.group_aid ?? '')}`
|
|
1220
|
+
: method.startsWith('group.') ? `group:${String(params.group_id ?? params.group_aid ?? '')}` : `p2p:${client._aid}`);
|
|
1221
|
+
client._delivery?.observeBackgroundPullResponse?.(ns, Number(params.after_seq ?? params.after_event_seq ?? 0), result, Number(params.limit ?? 50));
|
|
1093
1222
|
}
|
|
1094
1223
|
async transportCallWithIdentityRecovery(operation, method, params) {
|
|
1095
1224
|
try {
|