@opengeni/events 0.4.30 → 0.4.32-canary.36199476632001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +67 -2
- package/dist/index.js +244 -51
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +386 -45
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,14 @@ export type EventBusOptions = {
|
|
|
9
9
|
logger?: EventLogger;
|
|
10
10
|
/** Test/host transport seam; production defaults to the nats.js connector. */
|
|
11
11
|
connect?: typeof connect;
|
|
12
|
+
/**
|
|
13
|
+
* Metrics seam: called once for every subscription that ends without being
|
|
14
|
+
* unsubscribed (see {@link natsSubscriptionTerminationCounter}). A throwing
|
|
15
|
+
* sink is ignored.
|
|
16
|
+
*/
|
|
17
|
+
onSubscriptionTerminated?: (termination: NatsSubscriptionTermination) => void;
|
|
18
|
+
/** Test seam for the responder resubscribe backoff; production uses {@link natsResubscribeDelayMs}. */
|
|
19
|
+
resubscribeDelayMs?: (attempt: number) => number;
|
|
12
20
|
};
|
|
13
21
|
export { SESSION_EVENT_COALESCED_TEXT_TARGET_BYTES, coalesceSessionEventDeltas, coalesceSessionEventDeltasWithCoverage, type CoalescedSessionEventPage, } from "./coalesce.js";
|
|
14
22
|
/** Comfortably below NATS Core's common 1 MiB max_payload default. */
|
|
@@ -21,6 +29,54 @@ export declare const SESSION_EVENT_HTTP_PAGE_MAX_BYTES: number;
|
|
|
21
29
|
export declare const WORKSPACE_CONTROL_NATS_MESSAGE_MAX_BYTES: number;
|
|
22
30
|
/** Count+byte envelope for one workspace-control REST replay page. */
|
|
23
31
|
export declare const WORKSPACE_CONTROL_HTTP_PAGE_MAX_BYTES: number;
|
|
32
|
+
/**
|
|
33
|
+
* Closed label set for {@link NatsSubscriptionTermination}. Each value names one
|
|
34
|
+
* subscription role this package owns; no subject, tenant, or payload
|
|
35
|
+
* dimension is ever admitted, so a metric sink can use them as labels.
|
|
36
|
+
*/
|
|
37
|
+
export declare const NATS_SUBSCRIPTION_KINDS: readonly ["session_events", "workspace_control", "request_responder", "agent_events", "auth_callout"];
|
|
38
|
+
export type NatsSubscriptionKind = (typeof NATS_SUBSCRIPTION_KINDS)[number];
|
|
39
|
+
/**
|
|
40
|
+
* What happens after an unexpected end: a per-consumer subscription tells its
|
|
41
|
+
* consumer (`consumer_reconnect`, e.g. session SSE fails retryably and the
|
|
42
|
+
* client replays from Postgres), a process-lifetime responder resubscribes with
|
|
43
|
+
* bounded backoff (`resubscribe`), and a consumer that registered no hook only
|
|
44
|
+
* relies on its own durable re-read (`none`).
|
|
45
|
+
*/
|
|
46
|
+
export declare const NATS_SUBSCRIPTION_RECOVERIES: readonly ["consumer_reconnect", "resubscribe", "none"];
|
|
47
|
+
export type NatsSubscriptionRecovery = (typeof NATS_SUBSCRIPTION_RECOVERIES)[number];
|
|
48
|
+
export type NatsSubscriptionTermination = {
|
|
49
|
+
kind: NatsSubscriptionKind;
|
|
50
|
+
recovery: NatsSubscriptionRecovery;
|
|
51
|
+
};
|
|
52
|
+
/** Prometheus counter name for {@link natsSubscriptionTerminationCounter}. */
|
|
53
|
+
export declare const NATS_SUBSCRIPTION_TERMINATIONS_METRIC = "opengeni_nats_subscription_terminations_total";
|
|
54
|
+
/**
|
|
55
|
+
* Adapt a counter sink (the API/worker `Observability`) into the
|
|
56
|
+
* `onSubscriptionTerminated` hook. Labels are the closed kind/recovery sets.
|
|
57
|
+
*/
|
|
58
|
+
export declare function natsSubscriptionTerminationCounter(sink: {
|
|
59
|
+
incrementCounter(input: {
|
|
60
|
+
name: string;
|
|
61
|
+
help?: string;
|
|
62
|
+
labels?: Record<string, string>;
|
|
63
|
+
}): void;
|
|
64
|
+
}): (termination: NatsSubscriptionTermination) => void;
|
|
65
|
+
/** Per-subscription consumer options for {@link EventBus.subscribe}. */
|
|
66
|
+
export type BusSubscriptionOptions = {
|
|
67
|
+
/**
|
|
68
|
+
* Called at most once when the live transport subscription ends while the
|
|
69
|
+
* consumer still holds it (a broker-side error such as a permissions
|
|
70
|
+
* violation, or an iterator end the consumer did not request). Live events
|
|
71
|
+
* stop after this call, so the consumer must reconcile from Postgres: session
|
|
72
|
+
* and workspace-control SSE fail the stream retryably and the client
|
|
73
|
+
* reconnects and replays. Never called after the returned unsubscribe runs or
|
|
74
|
+
* while the bus itself is closing.
|
|
75
|
+
*/
|
|
76
|
+
onTerminated?: (error: unknown) => void;
|
|
77
|
+
};
|
|
78
|
+
/** Bounded resubscribe backoff for process-lifetime responders: 1 s doubling to 30 s, plus up to 1 s jitter. */
|
|
79
|
+
export declare function natsResubscribeDelayMs(attempt: number, random?: () => number): number;
|
|
24
80
|
export { decodeAuthRequest, mintAuthResponse, mintUserJwt, parseAgentConnectionName, workspaceAgentPermissions, type DecodedAuthRequest, type MintAuthResponseInput, type MintUserJwtInput, type NatsPermission, type NatsPermissions, } from "./nats-jwt.js";
|
|
25
81
|
export { connect, nkeys, type NatsConnection } from "nats";
|
|
26
82
|
/**
|
|
@@ -107,11 +163,18 @@ export type EventBus = {
|
|
|
107
163
|
* publish promise when this capability is unavailable.
|
|
108
164
|
*/
|
|
109
165
|
publishConfirmed?: (workspaceId: string, sessionId: string, events: SessionEvent[]) => Promise<void>;
|
|
110
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Live session-event fanout. `options.onTerminated` reports a transport
|
|
168
|
+
* subscription that ended while still held; implementations whose
|
|
169
|
+
* subscriptions can end on their own should call it so the consumer
|
|
170
|
+
* reconciles from Postgres. Buses that never end a held subscription may
|
|
171
|
+
* ignore it.
|
|
172
|
+
*/
|
|
173
|
+
subscribe: (workspaceId: string, sessionId: string, onEvents: (events: SessionEvent[]) => void | Promise<void>, options?: BusSubscriptionOptions) => Promise<() => void>;
|
|
111
174
|
/** Best-effort live invalidation; the event is already durable in Postgres. */
|
|
112
175
|
publishWorkspaceControl: (workspaceId: string, event: WorkspaceControlEvent) => Promise<void>;
|
|
113
176
|
/** One workspace subscription fans a control change to every open descendant view. */
|
|
114
|
-
subscribeWorkspaceControl: (workspaceId: string, onEvent: (event: WorkspaceControlEvent) => void | Promise<void
|
|
177
|
+
subscribeWorkspaceControl: (workspaceId: string, onEvent: (event: WorkspaceControlEvent) => void | Promise<void>, options?: BusSubscriptionOptions) => Promise<() => void>;
|
|
115
178
|
/**
|
|
116
179
|
* Issue a binary request/reply on a subject over the bus's NATS connection
|
|
117
180
|
* (the selfhosted control plane's exact claimed process subject). A new usage of what was
|
|
@@ -208,6 +271,8 @@ export declare function createResponderConnection(natsUrl: string, auth: NatsCon
|
|
|
208
271
|
name?: string;
|
|
209
272
|
logger?: EventLogger;
|
|
210
273
|
connect?: typeof connect;
|
|
274
|
+
onSubscriptionTerminated?: (termination: NatsSubscriptionTermination) => void;
|
|
275
|
+
resubscribeDelayMs?: (attempt: number) => number;
|
|
211
276
|
}): Promise<ResponderConnection>;
|
|
212
277
|
/**
|
|
213
278
|
* Optional timing seam for {@link appendAndPublishEvents}: `onAppend` fires after
|
package/dist/index.js
CHANGED
|
@@ -316,6 +316,7 @@ var silentLogger = {
|
|
|
316
316
|
var RECONNECT_OPTIONS = {
|
|
317
317
|
reconnect: true,
|
|
318
318
|
maxReconnectAttempts: -1,
|
|
319
|
+
ignoreAuthErrorAbort: true,
|
|
319
320
|
reconnectTimeWait: 2e3,
|
|
320
321
|
reconnectJitter: 1e3,
|
|
321
322
|
reconnectJitterTLS: 1e3,
|
|
@@ -380,6 +381,165 @@ function logConnectionStatus(nc, label, logger = silentLogger, onStatus) {
|
|
|
380
381
|
function isWarnNatsStatus(type) {
|
|
381
382
|
return type === "disconnect" || type === "error" || type === "staleConnection";
|
|
382
383
|
}
|
|
384
|
+
function subscriptionFailureAttributes(error) {
|
|
385
|
+
if (!error || typeof error !== "object") return { errorType: typeof error };
|
|
386
|
+
try {
|
|
387
|
+
const candidate = error;
|
|
388
|
+
return {
|
|
389
|
+
errorName: typeof candidate.name === "string" ? candidate.name.slice(0, 64) : "unknown",
|
|
390
|
+
...typeof candidate.code === "string" ? { errorCode: candidate.code.slice(0, 64) } : {}
|
|
391
|
+
};
|
|
392
|
+
} catch {
|
|
393
|
+
return { errorName: "unknown" };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
var NATS_SUBSCRIPTION_KINDS = [
|
|
397
|
+
"session_events",
|
|
398
|
+
"workspace_control",
|
|
399
|
+
"request_responder",
|
|
400
|
+
"agent_events",
|
|
401
|
+
"auth_callout"
|
|
402
|
+
];
|
|
403
|
+
var NATS_SUBSCRIPTION_RECOVERIES = ["consumer_reconnect", "resubscribe", "none"];
|
|
404
|
+
var NATS_SUBSCRIPTION_TERMINATIONS_METRIC = "opengeni_nats_subscription_terminations_total";
|
|
405
|
+
function natsSubscriptionTerminationCounter(sink) {
|
|
406
|
+
return ({ kind, recovery }) => {
|
|
407
|
+
sink.incrementCounter({
|
|
408
|
+
name: NATS_SUBSCRIPTION_TERMINATIONS_METRIC,
|
|
409
|
+
help: "NATS subscriptions that ended without being unsubscribed, by subscription kind and recovery path.",
|
|
410
|
+
labels: { kind, recovery }
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function natsResubscribeDelayMs(attempt, random = Math.random) {
|
|
415
|
+
const exponent = Number.isFinite(attempt) ? Math.min(Math.max(0, Math.trunc(attempt) - 1), 5) : 0;
|
|
416
|
+
const sample = random();
|
|
417
|
+
const unit = Number.isFinite(sample) ? Math.min(Math.max(sample, 0), 1 - Number.EPSILON) : 0;
|
|
418
|
+
return Math.min(3e4, 1e3 * 2 ** exponent) + Math.floor(unit * 1e3);
|
|
419
|
+
}
|
|
420
|
+
function pumpSubscription(subscription, context, onMessage, onEnded) {
|
|
421
|
+
const warn = context.logger?.warn ?? silentLogger.warn;
|
|
422
|
+
void (async () => {
|
|
423
|
+
let end = {};
|
|
424
|
+
try {
|
|
425
|
+
for await (const message of subscription) {
|
|
426
|
+
try {
|
|
427
|
+
await onMessage(message);
|
|
428
|
+
} catch (error) {
|
|
429
|
+
try {
|
|
430
|
+
warn("NATS subscription message dropped", {
|
|
431
|
+
label: context.label,
|
|
432
|
+
subject: context.subject,
|
|
433
|
+
...subscriptionFailureAttributes(error)
|
|
434
|
+
});
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} catch (error) {
|
|
440
|
+
end = { error };
|
|
441
|
+
}
|
|
442
|
+
try {
|
|
443
|
+
onEnded(end);
|
|
444
|
+
} catch {
|
|
445
|
+
}
|
|
446
|
+
})();
|
|
447
|
+
}
|
|
448
|
+
function reportSubscriptionTermination(context, recovery, end) {
|
|
449
|
+
try {
|
|
450
|
+
(context.logger?.warn ?? silentLogger.warn)(
|
|
451
|
+
"error" in end && end.error !== void 0 ? "NATS subscription ended with an error" : "NATS subscription ended unexpectedly",
|
|
452
|
+
{
|
|
453
|
+
label: context.label,
|
|
454
|
+
subject: context.subject,
|
|
455
|
+
recovery,
|
|
456
|
+
..."error" in end && end.error !== void 0 ? subscriptionFailureAttributes(end.error) : {}
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
} catch {
|
|
460
|
+
}
|
|
461
|
+
try {
|
|
462
|
+
context.onSubscriptionTerminated?.({ kind: context.kind, recovery });
|
|
463
|
+
} catch {
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function connectionShuttingDown(nc) {
|
|
467
|
+
return nc.isClosed() || nc.isDraining();
|
|
468
|
+
}
|
|
469
|
+
function subscribeWithTermination(nc, context, onMessage, options) {
|
|
470
|
+
const sub = nc.subscribe(context.subject);
|
|
471
|
+
let released = false;
|
|
472
|
+
const onTerminated = options?.onTerminated;
|
|
473
|
+
pumpSubscription(sub, context, onMessage, (end) => {
|
|
474
|
+
if (released || connectionShuttingDown(nc)) return;
|
|
475
|
+
reportSubscriptionTermination(context, onTerminated ? "consumer_reconnect" : "none", end);
|
|
476
|
+
try {
|
|
477
|
+
onTerminated?.("error" in end ? end.error : void 0);
|
|
478
|
+
} catch {
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
return () => {
|
|
482
|
+
released = true;
|
|
483
|
+
sub.unsubscribe();
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function subscribeWithResubscribe(nc, context, onMessage, resubscribeDelayMs = natsResubscribeDelayMs) {
|
|
487
|
+
let stopped = false;
|
|
488
|
+
let current = null;
|
|
489
|
+
let timer = null;
|
|
490
|
+
let consecutiveFailures = 0;
|
|
491
|
+
const pump = (sub) => {
|
|
492
|
+
current = sub;
|
|
493
|
+
pumpSubscription(
|
|
494
|
+
sub,
|
|
495
|
+
context,
|
|
496
|
+
async (message) => {
|
|
497
|
+
consecutiveFailures = 0;
|
|
498
|
+
await onMessage(message);
|
|
499
|
+
},
|
|
500
|
+
(end) => {
|
|
501
|
+
if (current === sub) current = null;
|
|
502
|
+
if (stopped || connectionShuttingDown(nc)) return;
|
|
503
|
+
reportSubscriptionTermination(context, "resubscribe", end);
|
|
504
|
+
schedule();
|
|
505
|
+
}
|
|
506
|
+
);
|
|
507
|
+
};
|
|
508
|
+
const schedule = () => {
|
|
509
|
+
if (stopped || connectionShuttingDown(nc)) return;
|
|
510
|
+
consecutiveFailures += 1;
|
|
511
|
+
let delayMs = 3e4;
|
|
512
|
+
try {
|
|
513
|
+
delayMs = resubscribeDelayMs(consecutiveFailures);
|
|
514
|
+
} catch {
|
|
515
|
+
}
|
|
516
|
+
timer = setTimeout(() => {
|
|
517
|
+
timer = null;
|
|
518
|
+
if (stopped || connectionShuttingDown(nc)) return;
|
|
519
|
+
let sub;
|
|
520
|
+
try {
|
|
521
|
+
sub = nc.subscribe(context.subject);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
reportSubscriptionTermination(context, "resubscribe", { error });
|
|
524
|
+
schedule();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
pump(sub);
|
|
528
|
+
}, delayMs);
|
|
529
|
+
timer.unref?.();
|
|
530
|
+
};
|
|
531
|
+
pump(nc.subscribe(context.subject));
|
|
532
|
+
return () => {
|
|
533
|
+
stopped = true;
|
|
534
|
+
if (timer) {
|
|
535
|
+
clearTimeout(timer);
|
|
536
|
+
timer = null;
|
|
537
|
+
}
|
|
538
|
+
const sub = current;
|
|
539
|
+
current = null;
|
|
540
|
+
sub?.unsubscribe();
|
|
541
|
+
};
|
|
542
|
+
}
|
|
383
543
|
var SESSION_EVENT_DURABLE_FANOUT_CAPABILITY_VERSION = 1;
|
|
384
544
|
function requireSessionEventDurableFanoutCapability(bus) {
|
|
385
545
|
const capability = bus?.sessionEventDurableFanout;
|
|
@@ -484,7 +644,7 @@ async function createNatsEventBus(natsUrl, auth, options = {}) {
|
|
|
484
644
|
publishSessionEvents(workspaceId, sessionId, events);
|
|
485
645
|
await flushConfirmedWithTimeout(nc, PUBLISH_FLUSH_TIMEOUT_MS);
|
|
486
646
|
},
|
|
487
|
-
subscribe: async (workspaceId, sessionId, onEvents) => subscribeSession(nc, workspaceId, sessionId, onEvents),
|
|
647
|
+
subscribe: async (workspaceId, sessionId, onEvents, subscriptionOptions) => subscribeSession(nc, workspaceId, sessionId, onEvents, options, subscriptionOptions),
|
|
488
648
|
publishWorkspaceControl: async (workspaceId, event) => {
|
|
489
649
|
try {
|
|
490
650
|
const encoded = workspaceControlEventNatsPayload(event);
|
|
@@ -502,22 +662,27 @@ async function createNatsEventBus(natsUrl, auth, options = {}) {
|
|
|
502
662
|
}
|
|
503
663
|
await flushWithTimeout(nc, PUBLISH_FLUSH_TIMEOUT_MS);
|
|
504
664
|
},
|
|
505
|
-
subscribeWorkspaceControl: async (workspaceId, onEvent) =>
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
665
|
+
subscribeWorkspaceControl: async (workspaceId, onEvent, subscriptionOptions) => subscribeWithTermination(
|
|
666
|
+
nc,
|
|
667
|
+
{
|
|
668
|
+
label: "workspace-control",
|
|
669
|
+
kind: "workspace_control",
|
|
670
|
+
subject: workspaceControlSubject(workspaceId),
|
|
671
|
+
logger: options.logger,
|
|
672
|
+
onSubscriptionTerminated: options.onSubscriptionTerminated
|
|
673
|
+
},
|
|
674
|
+
async (msg) => {
|
|
675
|
+
await onEvent(
|
|
676
|
+
boundWorkspaceControlEvent(codec.decode(msg.data), {
|
|
677
|
+
surface: "nats_legacy_guard"
|
|
678
|
+
})
|
|
679
|
+
);
|
|
680
|
+
},
|
|
681
|
+
subscriptionOptions
|
|
682
|
+
),
|
|
518
683
|
request: async (subject, payload, opts) => requestReply(nc, subject, payload, opts.timeoutMs),
|
|
519
|
-
subscribeRequests: (subject, handler) => subscribeRequests(nc, subject, handler),
|
|
520
|
-
subscribeAgentEvents: (subject, handler) => subscribeAgentEvents(nc, subject, handler),
|
|
684
|
+
subscribeRequests: (subject, handler) => subscribeRequests(nc, subject, handler, options),
|
|
685
|
+
subscribeAgentEvents: (subject, handler) => subscribeAgentEvents(nc, subject, handler, options),
|
|
521
686
|
getRequestConnection: () => requestConnection,
|
|
522
687
|
getOpStreamConnection: () => opStreamConnection,
|
|
523
688
|
isConnected: () => connected && !nc.isClosed() && !nc.isDraining(),
|
|
@@ -544,22 +709,30 @@ async function createResponderConnection(natsUrl, auth, subject, handler, option
|
|
|
544
709
|
options.name ? `auth-callout:${options.name}` : "auth-callout",
|
|
545
710
|
options.logger
|
|
546
711
|
);
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
712
|
+
const unsubscribe = subscribeWithResubscribe(
|
|
713
|
+
nc,
|
|
714
|
+
{
|
|
715
|
+
label: options.name ? `auth-callout:${options.name}` : "auth-callout",
|
|
716
|
+
kind: "auth_callout",
|
|
717
|
+
subject,
|
|
718
|
+
logger: options.logger,
|
|
719
|
+
onSubscriptionTerminated: options.onSubscriptionTerminated
|
|
720
|
+
},
|
|
721
|
+
async (msg) => {
|
|
550
722
|
if (!msg.reply) {
|
|
551
|
-
|
|
723
|
+
return;
|
|
552
724
|
}
|
|
553
725
|
try {
|
|
554
726
|
const reply = await handler(msg.data, msg.subject);
|
|
555
727
|
msg.respond(reply);
|
|
556
728
|
} catch {
|
|
557
729
|
}
|
|
558
|
-
}
|
|
559
|
-
|
|
730
|
+
},
|
|
731
|
+
options.resubscribeDelayMs
|
|
732
|
+
);
|
|
560
733
|
return {
|
|
561
734
|
close: async () => {
|
|
562
|
-
|
|
735
|
+
unsubscribe();
|
|
563
736
|
await nc.drain();
|
|
564
737
|
}
|
|
565
738
|
};
|
|
@@ -647,56 +820,71 @@ async function appendAndPublishTurnEventsFenced(db, bus, workspaceId, sessionId,
|
|
|
647
820
|
observeSince(observe?.onPublish, publishStartedAt, result.events.length);
|
|
648
821
|
return result;
|
|
649
822
|
}
|
|
650
|
-
function subscribeSession(nc, workspaceId, sessionId, onEvents) {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
823
|
+
function subscribeSession(nc, workspaceId, sessionId, onEvents, busOptions, subscriptionOptions) {
|
|
824
|
+
return subscribeWithTermination(
|
|
825
|
+
nc,
|
|
826
|
+
{
|
|
827
|
+
label: "session-events",
|
|
828
|
+
kind: "session_events",
|
|
829
|
+
subject: sessionSubject(workspaceId, sessionId),
|
|
830
|
+
logger: busOptions.logger,
|
|
831
|
+
onSubscriptionTerminated: busOptions.onSubscriptionTerminated
|
|
832
|
+
},
|
|
833
|
+
async (msg) => {
|
|
654
834
|
const decoded = codec.decode(msg.data);
|
|
655
835
|
const events = ("events" in decoded ? decoded.events : [decoded]).map(
|
|
656
836
|
(event) => boundSessionEventForSurface(event, "nats_legacy_guard")
|
|
657
837
|
);
|
|
658
838
|
await onEvents(events);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
sub.unsubscribe();
|
|
663
|
-
};
|
|
839
|
+
},
|
|
840
|
+
subscriptionOptions
|
|
841
|
+
);
|
|
664
842
|
}
|
|
665
843
|
async function requestReply(nc, subject, payload, timeout) {
|
|
666
844
|
const msg = await nc.request(subject, payload, { timeout });
|
|
667
845
|
return { data: msg.data };
|
|
668
846
|
}
|
|
669
|
-
function subscribeRequests(nc, subject, handler) {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
847
|
+
function subscribeRequests(nc, subject, handler, busOptions) {
|
|
848
|
+
return subscribeWithResubscribe(
|
|
849
|
+
nc,
|
|
850
|
+
{
|
|
851
|
+
label: "request-responder",
|
|
852
|
+
kind: "request_responder",
|
|
853
|
+
subject,
|
|
854
|
+
logger: busOptions.logger,
|
|
855
|
+
onSubscriptionTerminated: busOptions.onSubscriptionTerminated
|
|
856
|
+
},
|
|
857
|
+
async (msg) => {
|
|
673
858
|
if (!msg.reply) {
|
|
674
|
-
|
|
859
|
+
return;
|
|
675
860
|
}
|
|
676
861
|
try {
|
|
677
862
|
const reply = await handler(msg.data, msg.subject);
|
|
678
863
|
msg.respond(reply);
|
|
679
864
|
} catch {
|
|
680
865
|
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
sub.unsubscribe();
|
|
685
|
-
};
|
|
866
|
+
},
|
|
867
|
+
busOptions.resubscribeDelayMs
|
|
868
|
+
);
|
|
686
869
|
}
|
|
687
|
-
function subscribeAgentEvents(nc, subject, handler) {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
870
|
+
function subscribeAgentEvents(nc, subject, handler, busOptions) {
|
|
871
|
+
return subscribeWithResubscribe(
|
|
872
|
+
nc,
|
|
873
|
+
{
|
|
874
|
+
label: "agent-events",
|
|
875
|
+
kind: "agent_events",
|
|
876
|
+
subject,
|
|
877
|
+
logger: busOptions.logger,
|
|
878
|
+
onSubscriptionTerminated: busOptions.onSubscriptionTerminated
|
|
879
|
+
},
|
|
880
|
+
async (msg) => {
|
|
691
881
|
try {
|
|
692
882
|
await handler(msg.data, msg.subject);
|
|
693
883
|
} catch {
|
|
694
884
|
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
sub.unsubscribe();
|
|
699
|
-
};
|
|
885
|
+
},
|
|
886
|
+
busOptions.resubscribeDelayMs
|
|
887
|
+
);
|
|
700
888
|
}
|
|
701
889
|
function formatSse(event, idSequence = event.sequence) {
|
|
702
890
|
const trustedId = Number.isSafeInteger(idSequence) && idSequence >= event.sequence ? idSequence : event.sequence;
|
|
@@ -853,6 +1041,9 @@ function workspaceControlSubject(workspaceId) {
|
|
|
853
1041
|
return `workspaces.${workspaceId}.control`;
|
|
854
1042
|
}
|
|
855
1043
|
export {
|
|
1044
|
+
NATS_SUBSCRIPTION_KINDS,
|
|
1045
|
+
NATS_SUBSCRIPTION_RECOVERIES,
|
|
1046
|
+
NATS_SUBSCRIPTION_TERMINATIONS_METRIC,
|
|
856
1047
|
SESSION_EVENT_COALESCED_TEXT_TARGET_BYTES,
|
|
857
1048
|
SESSION_EVENT_DURABLE_FANOUT_CAPABILITY_VERSION,
|
|
858
1049
|
SESSION_EVENT_HTTP_PAGE_MAX_BYTES,
|
|
@@ -875,6 +1066,8 @@ export {
|
|
|
875
1066
|
formatWorkspaceControlEventSse,
|
|
876
1067
|
mintAuthResponse,
|
|
877
1068
|
mintUserJwt,
|
|
1069
|
+
natsResubscribeDelayMs,
|
|
1070
|
+
natsSubscriptionTerminationCounter,
|
|
878
1071
|
nkeys2 as nkeys,
|
|
879
1072
|
observeSince,
|
|
880
1073
|
parseAgentConnectionName,
|