@llblab/pi-telegram 0.50.1 → 0.51.1
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/AGENTS.md +10 -8
- package/BACKLOG.md +13 -32
- package/CHANGELOG.md +16 -0
- package/README.md +4 -3
- package/dist/lib/bindings.d.ts +4 -2
- package/dist/lib/bindings.js +5 -5
- package/dist/lib/bus-follower.d.ts +4 -2
- package/dist/lib/bus-follower.js +99 -10
- package/dist/lib/bus-leader.d.ts +9 -3
- package/dist/lib/bus-leader.js +231 -71
- package/dist/lib/bus.d.ts +4 -0
- package/dist/lib/bus.js +34 -7
- package/dist/lib/commands.d.ts +5 -0
- package/dist/lib/commands.js +9 -0
- package/dist/lib/extension.js +68 -3
- package/dist/lib/journal.d.ts +3 -0
- package/dist/lib/journal.js +13 -0
- package/dist/lib/lifecycle.d.ts +2 -0
- package/dist/lib/lifecycle.js +25 -4
- package/dist/lib/locks.d.ts +1 -0
- package/dist/lib/locks.js +32 -12
- package/dist/lib/paths.d.ts +10 -0
- package/dist/lib/paths.js +22 -1
- package/dist/lib/polling.js +2 -2
- package/dist/lib/queue.d.ts +9 -1
- package/dist/lib/queue.js +64 -13
- package/dist/lib/replies.d.ts +4 -0
- package/dist/lib/replies.js +14 -0
- package/dist/lib/routing.d.ts +1 -0
- package/dist/lib/routing.js +5 -0
- package/dist/lib/sync.d.ts +9 -0
- package/dist/lib/sync.js +41 -1
- package/dist/lib/telegram-api.d.ts +9 -1
- package/dist/lib/telegram-api.js +23 -3
- package/dist/lib/thread-cleanup-manager.js +7 -2
- package/dist/lib/threads.d.ts +2 -0
- package/dist/lib/threads.js +68 -37
- package/dist/lib/updates.d.ts +6 -4
- package/dist/lib/updates.js +134 -61
- package/dist/lib/workspace-admission.d.ts +9 -0
- package/dist/lib/workspace-admission.js +49 -3
- package/dist/lib/workspace-retirement.d.ts +77 -6
- package/dist/lib/workspace-retirement.js +384 -8
- package/dist/lib/workspace-slots.d.ts +3 -0
- package/dist/lib/workspace-slots.js +6 -0
- package/dist/package.json +1 -1
- package/docs/architecture.md +22 -15
- package/docs/multi-instance-bus.md +32 -11
- package/docs/public-api.md +1 -1
- package/docs/updates.md +2 -0
- package/lib/bindings.ts +12 -7
- package/lib/bus-follower.ts +82 -14
- package/lib/bus-leader.ts +236 -94
- package/lib/bus.ts +39 -9
- package/lib/commands.ts +19 -0
- package/lib/extension.ts +78 -2
- package/lib/journal.ts +14 -0
- package/lib/lifecycle.ts +23 -4
- package/lib/locks.ts +32 -13
- package/lib/paths.ts +29 -1
- package/lib/polling.ts +2 -2
- package/lib/queue.ts +77 -19
- package/lib/replies.ts +18 -0
- package/lib/routing.ts +7 -0
- package/lib/sync.ts +45 -1
- package/lib/telegram-api.ts +30 -2
- package/lib/thread-cleanup-manager.ts +11 -3
- package/lib/threads.ts +73 -36
- package/lib/updates.ts +145 -78
- package/lib/workspace-admission.ts +67 -4
- package/lib/workspace-retirement.ts +465 -7
- package/lib/workspace-slots.ts +7 -0
- package/package.json +1 -1
package/lib/bindings.ts
CHANGED
|
@@ -52,6 +52,7 @@ export interface TelegramQueueBindingRuntime<TContext> {
|
|
|
52
52
|
mutation: Queue.TelegramQueueMutationController<TContext>;
|
|
53
53
|
dispatchNext: (ctx: TContext) => void;
|
|
54
54
|
requestNextDispatchAnnouncement: () => void;
|
|
55
|
+
cancelNextDispatchAnnouncement: () => void;
|
|
55
56
|
watchdog: Queue.TelegramQueueDispatchWatchdogRuntime<TContext>;
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -69,12 +70,12 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
69
70
|
onItemsDiscarded: (
|
|
70
71
|
items: readonly Queue.TelegramQueueItem<TContext>[],
|
|
71
72
|
ctx: TContext,
|
|
72
|
-
) =>
|
|
73
|
+
) => boolean;
|
|
73
74
|
isItemReady: (item: Queue.TelegramQueueItem<TContext>) => boolean;
|
|
74
75
|
onPromptHandedOff?: (
|
|
75
76
|
item: Queue.PendingTelegramTurn,
|
|
76
77
|
ctx: TContext,
|
|
77
|
-
) =>
|
|
78
|
+
) => boolean;
|
|
78
79
|
onControlSettled: (
|
|
79
80
|
item: Queue.PendingTelegramControlItem<TContext>,
|
|
80
81
|
ctx: TContext,
|
|
@@ -96,6 +97,9 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
96
97
|
updateStatus: (ctx: TContext, error?: string) => void;
|
|
97
98
|
sendTextReply: Queue.TelegramQueueDispatchRuntimeDeps<TContext>["sendTextReply"];
|
|
98
99
|
sendUserMessage: Queue.TelegramQueueDispatchRuntimeDeps<TContext>["sendUserMessage"];
|
|
100
|
+
reconcileNextDispatchAnnouncementReplyOwnership?: (
|
|
101
|
+
item: Queue.PendingTelegramTurn,
|
|
102
|
+
) => void;
|
|
99
103
|
recordRuntimeEvent?: TelegramRuntimeEventRecorder;
|
|
100
104
|
}): TelegramQueueBindingRuntime<TContext> {
|
|
101
105
|
const settleDiscardedItems = (
|
|
@@ -108,8 +112,7 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
108
112
|
if (durableItems.length === 0) return true;
|
|
109
113
|
const settlement = deps.admission.getSettlement();
|
|
110
114
|
if (!settlement) return false;
|
|
111
|
-
settlement.onItemsDiscarded(durableItems, ctx);
|
|
112
|
-
return durableItems.every((item) => !settlement.isItemReady(item));
|
|
115
|
+
return settlement.onItemsDiscarded(durableItems, ctx) === true;
|
|
113
116
|
};
|
|
114
117
|
const mutation = Queue.createTelegramQueueMutationController({
|
|
115
118
|
...deps.store,
|
|
@@ -150,8 +153,7 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
150
153
|
if ((item.admissionReceipts?.length ?? 0) === 0) return true;
|
|
151
154
|
const settlement = deps.admission.getSettlement();
|
|
152
155
|
if (!settlement?.onPromptHandedOff) return false;
|
|
153
|
-
settlement.onPromptHandedOff(item, ctx);
|
|
154
|
-
return !settlement.isItemReady(item);
|
|
156
|
+
return settlement.onPromptHandedOff(item, ctx) === true;
|
|
155
157
|
},
|
|
156
158
|
onControlSettled(item, ctx) {
|
|
157
159
|
deps.admission.getSettlement()?.onControlSettled(item, ctx);
|
|
@@ -161,6 +163,8 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
161
163
|
},
|
|
162
164
|
updateStatus: deps.updateStatus,
|
|
163
165
|
sendTextReply: deps.sendTextReply,
|
|
166
|
+
reconcileNextDispatchAnnouncementReplyOwnership:
|
|
167
|
+
deps.reconcileNextDispatchAnnouncementReplyOwnership,
|
|
164
168
|
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
165
169
|
...deps.promptDispatch,
|
|
166
170
|
sendUserMessage: deps.sendUserMessage,
|
|
@@ -169,6 +173,7 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
|
|
|
169
173
|
mutation,
|
|
170
174
|
dispatchNext: dispatch.dispatchNext,
|
|
171
175
|
requestNextDispatchAnnouncement: dispatch.requestNextDispatchAnnouncement,
|
|
176
|
+
cancelNextDispatchAnnouncement: dispatch.cancelNextDispatchAnnouncement,
|
|
172
177
|
watchdog: Queue.createTelegramQueueDispatchWatchdogRuntime({
|
|
173
178
|
hasQueuedItems: deps.store.hasQueuedItems,
|
|
174
179
|
dispatchNextQueuedTelegramTurn: dispatch.dispatchNext,
|
|
@@ -1143,7 +1148,7 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1143
1148
|
getActiveTurn: activeTurnRuntime.get,
|
|
1144
1149
|
loadConfig: configStore.load,
|
|
1145
1150
|
extractAssistant: Replies.extractRunAssistantMessage,
|
|
1146
|
-
|
|
1151
|
+
isAssistantAlreadyPublished: (assistant) =>
|
|
1147
1152
|
!!assistant.text && assistantOutputRuntime.hasAdmittedTelegramIntermediate(assistant.text),
|
|
1148
1153
|
getFoldQueuedPromptsIntoHistory:
|
|
1149
1154
|
lifecycle.shouldFoldQueuedPromptsIntoHistory,
|
package/lib/bus-follower.ts
CHANGED
|
@@ -11,7 +11,11 @@ import { basename } from "node:path";
|
|
|
11
11
|
import * as Sync from "./sync.ts";
|
|
12
12
|
import * as Threads from "./threads.ts";
|
|
13
13
|
import { parseTelegramUpdateJournalQueueOwner, type TelegramUpdateJournalStoreOptions } from "./journal.ts";
|
|
14
|
-
import
|
|
14
|
+
import {
|
|
15
|
+
TELEGRAM_BUS_LEADER_STALE_HEARTBEAT_MS,
|
|
16
|
+
type TelegramLockEntry,
|
|
17
|
+
type TelegramLockState,
|
|
18
|
+
} from "./locks.ts";
|
|
15
19
|
import type {
|
|
16
20
|
TelegramQueueHandoffPayload,
|
|
17
21
|
TelegramQueueHandoffStageResult,
|
|
@@ -60,6 +64,8 @@ export const TELEGRAM_BUS_FOLLOWER_PROMOTION_GRACE_MS = 2_500;
|
|
|
60
64
|
export const TELEGRAM_FOLLOWER_SESSION_HANDOFF_TTL_MS = 30_000;
|
|
61
65
|
export const TELEGRAM_BUS_FOLLOWER_CLIENT_TIMEOUT_MS = 30_000;
|
|
62
66
|
export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_WAIT_MS = 30_000;
|
|
67
|
+
export const TELEGRAM_BUS_FOLLOWER_HEARTBEAT_TIMEOUT_MS =
|
|
68
|
+
TELEGRAM_BUS_LEADER_STALE_HEARTBEAT_MS;
|
|
63
69
|
export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_RETRY_ATTEMPTS =
|
|
64
70
|
TELEGRAM_BUS_REGISTRATION_RETRY.attempts;
|
|
65
71
|
export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_RETRY_DELAY_MS =
|
|
@@ -126,7 +132,7 @@ export interface TelegramBusFollowerRegistrationRuntime<TContext> {
|
|
|
126
132
|
restoreWorkspace?: boolean;
|
|
127
133
|
},
|
|
128
134
|
) => Promise<boolean>;
|
|
129
|
-
setContext: (ctx: TContext) => void
|
|
135
|
+
setContext: (ctx: TContext) => void | Promise<void>;
|
|
130
136
|
disconnectFromLeader?: () => Promise<boolean>;
|
|
131
137
|
renameThread?: (
|
|
132
138
|
target: TelegramTarget & { threadId: number },
|
|
@@ -301,6 +307,7 @@ export interface TelegramBusFollowerRegistrationRuntimeDeps<
|
|
|
301
307
|
registrationRetryAttempts?: number;
|
|
302
308
|
registrationRetryDelayMs?: number;
|
|
303
309
|
heartbeatMs?: number;
|
|
310
|
+
heartbeatTimeoutMs?: number;
|
|
304
311
|
recordRuntimeEvent?: (
|
|
305
312
|
category: string,
|
|
306
313
|
error: unknown,
|
|
@@ -623,6 +630,22 @@ export function createTelegramBusFollowerRuntimeAssembly<
|
|
|
623
630
|
>(
|
|
624
631
|
ports: TelegramBusFollowerRuntimeAssemblyPorts<TContext>,
|
|
625
632
|
): TelegramBusFollowerRuntimeAssembly<TContext> {
|
|
633
|
+
// Binding startup needs registration identity before it can grant inbound authority.
|
|
634
|
+
let readyContext: { generation: string; ctx: TContext; sessionGeneration: number | undefined } | undefined;
|
|
635
|
+
const isReadyContext = (ctx?: TContext): boolean => Boolean(readyContext &&
|
|
636
|
+
(ctx === undefined || readyContext.ctx === ctx) &&
|
|
637
|
+
ports.registrationState.getGeneration() === readyContext.generation &&
|
|
638
|
+
ports.registration.getSessionGeneration?.() === readyContext.sessionGeneration &&
|
|
639
|
+
ports.registration.isContextActive?.(readyContext.ctx) !== false);
|
|
640
|
+
const prepareContext = async (ctx: TContext): Promise<void> => {
|
|
641
|
+
const generation = ports.registrationState.getGeneration();
|
|
642
|
+
const sessionGeneration = ports.registration.getSessionGeneration?.();
|
|
643
|
+
readyContext = undefined;
|
|
644
|
+
await ports.registration.onRegistered?.(ctx);
|
|
645
|
+
if (generation && ports.registrationState.getGeneration() === generation &&
|
|
646
|
+
ports.registration.getSessionGeneration?.() === sessionGeneration &&
|
|
647
|
+
ports.registration.isContextActive?.(ctx) !== false) readyContext = { generation, ctx, sessionGeneration };
|
|
648
|
+
};
|
|
626
649
|
const sharedRuntimeDeps = {
|
|
627
650
|
instanceId: ports.instanceId,
|
|
628
651
|
registrationState: ports.registrationState,
|
|
@@ -632,7 +655,9 @@ export function createTelegramBusFollowerRuntimeAssembly<
|
|
|
632
655
|
...ports.receiver,
|
|
633
656
|
instanceId: ports.instanceId,
|
|
634
657
|
recordRuntimeEvent: ports.recordRuntimeEvent,
|
|
635
|
-
getRegistrationGeneration
|
|
658
|
+
getRegistrationGeneration() {
|
|
659
|
+
return isReadyContext() ? readyContext?.generation : undefined;
|
|
660
|
+
},
|
|
636
661
|
handleReplaceTarget: createTelegramBusFollowerTargetReplacementHandler({
|
|
637
662
|
...ports.targetReplacement,
|
|
638
663
|
...sharedRuntimeDeps,
|
|
@@ -650,8 +675,21 @@ export function createTelegramBusFollowerRuntimeAssembly<
|
|
|
650
675
|
...sharedRuntimeDeps,
|
|
651
676
|
startReceiving: receiver.start,
|
|
652
677
|
stopReceiving: receiver.stop,
|
|
678
|
+
onRegistered: prepareContext,
|
|
653
679
|
onHeartbeatFailure: recovery,
|
|
654
680
|
});
|
|
681
|
+
const baseRegistration = registration;
|
|
682
|
+
registration = {
|
|
683
|
+
...baseRegistration,
|
|
684
|
+
async setContext(ctx) {
|
|
685
|
+
const sessionGeneration = ports.registration.getSessionGeneration?.();
|
|
686
|
+
if (ports.registration.isContextActive?.(ctx) === false) return;
|
|
687
|
+
await baseRegistration.setContext(ctx);
|
|
688
|
+
if (ports.registration.getSessionGeneration?.() !== sessionGeneration ||
|
|
689
|
+
ports.registration.isContextActive?.(ctx) === false) return;
|
|
690
|
+
if (!isReadyContext(ctx)) await prepareContext(ctx);
|
|
691
|
+
},
|
|
692
|
+
};
|
|
655
693
|
return { receiver, registration };
|
|
656
694
|
}
|
|
657
695
|
|
|
@@ -1194,7 +1232,13 @@ export function createTelegramBusFollowerSessionRefreshHook<TContext>(
|
|
|
1194
1232
|
}
|
|
1195
1233
|
if (!deps.registrationState.isRegistered()) return;
|
|
1196
1234
|
if (deps.isSessionActive && !deps.isSessionActive(ctx)) return;
|
|
1197
|
-
|
|
1235
|
+
try {
|
|
1236
|
+
await deps.registrationRuntime.setContext(ctx);
|
|
1237
|
+
} catch (error) {
|
|
1238
|
+
deps.recordRuntimeEvent("bus", error, { phase: "follower-session-refresh" });
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
if (deps.isSessionActive && !deps.isSessionActive(ctx)) return;
|
|
1198
1242
|
deps.updateStatus(ctx);
|
|
1199
1243
|
deps.recordRuntimeEvent(
|
|
1200
1244
|
"bus",
|
|
@@ -1582,6 +1626,10 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1582
1626
|
const getNowMs = deps.getNowMs ?? Date.now;
|
|
1583
1627
|
const getPid = deps.getPid ?? (() => process.pid);
|
|
1584
1628
|
const heartbeatMs = deps.heartbeatMs ?? 1000;
|
|
1629
|
+
const heartbeatTimeoutMs =
|
|
1630
|
+
deps.heartbeatTimeoutMs ??
|
|
1631
|
+
deps.timeoutMs ??
|
|
1632
|
+
TELEGRAM_BUS_FOLLOWER_HEARTBEAT_TIMEOUT_MS;
|
|
1585
1633
|
const registrationTimeoutMs =
|
|
1586
1634
|
deps.registrationTimeoutMs ?? deps.timeoutMs ?? 30000;
|
|
1587
1635
|
const registrationRetryAttempts =
|
|
@@ -1596,6 +1644,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1596
1644
|
let activeLeaderSocketPath: string | undefined;
|
|
1597
1645
|
let activeAuthSecret: string | undefined;
|
|
1598
1646
|
let activeRegistrationGeneration: string | undefined;
|
|
1647
|
+
let registrationAttempt: { ctx: TContext; sessionGeneration: number | undefined } | undefined;
|
|
1599
1648
|
let activeContext: TContext | undefined;
|
|
1600
1649
|
let lastKnownTarget: TelegramTarget | undefined;
|
|
1601
1650
|
let lastKnownSlot: string | undefined;
|
|
@@ -1606,6 +1655,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1606
1655
|
heartbeatInterval = undefined;
|
|
1607
1656
|
};
|
|
1608
1657
|
const stop = () => {
|
|
1658
|
+
registrationAttempt = undefined;
|
|
1609
1659
|
stopHeartbeat();
|
|
1610
1660
|
activeAuthSecret = undefined;
|
|
1611
1661
|
activeRegistrationGeneration = undefined;
|
|
@@ -1640,7 +1690,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1640
1690
|
try {
|
|
1641
1691
|
const response = await sendTelegramBusLocalEnvelope({
|
|
1642
1692
|
socketPath: leaderSocketPath,
|
|
1643
|
-
timeoutMs:
|
|
1693
|
+
timeoutMs: heartbeatTimeoutMs,
|
|
1644
1694
|
retry: getTelegramBusTransportRetryPolicy({
|
|
1645
1695
|
endpoint: leaderSocketPath,
|
|
1646
1696
|
operation: "operation",
|
|
@@ -1729,6 +1779,24 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1729
1779
|
};
|
|
1730
1780
|
return {
|
|
1731
1781
|
registerWithLeader: async (ctx, leader, options) => {
|
|
1782
|
+
if (deps.isContextActive?.(ctx) === false) return false;
|
|
1783
|
+
const sessionGeneration = deps.getSessionGeneration?.();
|
|
1784
|
+
const attempt = { ctx, sessionGeneration };
|
|
1785
|
+
registrationAttempt = attempt;
|
|
1786
|
+
const isCurrentRequest = () => registrationAttempt === attempt &&
|
|
1787
|
+
deps.getSessionGeneration?.() === sessionGeneration && deps.isContextActive?.(ctx) !== false;
|
|
1788
|
+
const abandonOwnedRequest = async (): Promise<void> => {
|
|
1789
|
+
if (registrationAttempt !== attempt) return;
|
|
1790
|
+
registrationAttempt = undefined;
|
|
1791
|
+
stopHeartbeat();
|
|
1792
|
+
activeLeaderSocketPath = undefined;
|
|
1793
|
+
activeAuthSecret = undefined;
|
|
1794
|
+
activeRegistrationGeneration = undefined;
|
|
1795
|
+
activeContext = undefined;
|
|
1796
|
+
deps.registrationState?.setRegistered(false);
|
|
1797
|
+
deps.setActiveAuthSecret?.(undefined);
|
|
1798
|
+
await deps.stopReceiving?.();
|
|
1799
|
+
};
|
|
1732
1800
|
const pendingHandoff = options
|
|
1733
1801
|
? undefined
|
|
1734
1802
|
: getTelegramFollowerSessionHandoff();
|
|
@@ -1750,6 +1818,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1750
1818
|
deps.getLeaderSocketPath?.() ??
|
|
1751
1819
|
getTelegramBusSocketPath();
|
|
1752
1820
|
await deps.startReceiving?.();
|
|
1821
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1753
1822
|
activeAuthSecret = deps.getLeaderAuthSecret
|
|
1754
1823
|
? deps.getLeaderAuthSecret(leader)
|
|
1755
1824
|
: leader?.busSecret;
|
|
@@ -1781,7 +1850,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1781
1850
|
sessionId: deps.getSessionId?.(ctx),
|
|
1782
1851
|
pid: getPid(),
|
|
1783
1852
|
processBirthId: deps.getProcessBirthId?.(),
|
|
1784
|
-
sessionGeneration
|
|
1853
|
+
sessionGeneration,
|
|
1785
1854
|
target:
|
|
1786
1855
|
registrationOptions?.target ??
|
|
1787
1856
|
deps.registrationState?.getTarget() ??
|
|
@@ -1815,6 +1884,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1815
1884
|
},
|
|
1816
1885
|
});
|
|
1817
1886
|
} catch (error) {
|
|
1887
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1818
1888
|
stopHeartbeat();
|
|
1819
1889
|
activeLeaderSocketPath = undefined;
|
|
1820
1890
|
activeAuthSecret = undefined;
|
|
@@ -1823,14 +1893,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1823
1893
|
await deps.stopReceiving?.();
|
|
1824
1894
|
throw error;
|
|
1825
1895
|
}
|
|
1826
|
-
if (
|
|
1827
|
-
stopHeartbeat();
|
|
1828
|
-
activeLeaderSocketPath = undefined;
|
|
1829
|
-
activeAuthSecret = undefined;
|
|
1830
|
-
deps.setActiveAuthSecret?.(undefined);
|
|
1831
|
-
await deps.stopReceiving?.();
|
|
1832
|
-
return false;
|
|
1833
|
-
}
|
|
1896
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1834
1897
|
const compatibility = getTelegramBusProtocolCompatibility({
|
|
1835
1898
|
local: deps.protocolIdentity,
|
|
1836
1899
|
remote: response?.kind === "bus.ack" ? response.protocol : undefined,
|
|
@@ -1880,6 +1943,7 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1880
1943
|
try {
|
|
1881
1944
|
await deps.onRegistered?.(ctx);
|
|
1882
1945
|
} catch (error) {
|
|
1946
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1883
1947
|
stopHeartbeat();
|
|
1884
1948
|
activeLeaderSocketPath = undefined;
|
|
1885
1949
|
activeAuthSecret = undefined;
|
|
@@ -1889,7 +1953,9 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1889
1953
|
await deps.stopReceiving?.();
|
|
1890
1954
|
throw error;
|
|
1891
1955
|
}
|
|
1956
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1892
1957
|
await requestHeartbeat();
|
|
1958
|
+
if (!isCurrentRequest()) { await abandonOwnedRequest(); return false; }
|
|
1893
1959
|
startHeartbeat(leaderSocketPath);
|
|
1894
1960
|
if (
|
|
1895
1961
|
pendingHandoffOptions &&
|
|
@@ -1909,6 +1975,8 @@ export function createTelegramBusFollowerRegistrationRuntime<
|
|
|
1909
1975
|
return false;
|
|
1910
1976
|
},
|
|
1911
1977
|
setContext(ctx) {
|
|
1978
|
+
if (registrationAttempt && (registrationAttempt.ctx !== ctx ||
|
|
1979
|
+
registrationAttempt.sessionGeneration !== deps.getSessionGeneration?.())) registrationAttempt = undefined;
|
|
1912
1980
|
activeContext = ctx;
|
|
1913
1981
|
},
|
|
1914
1982
|
async setThreadDisplayMode(mode) {
|