





















@@ -570,6 +570,8 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage
570570return;
571571}
572572573+let trackedPromise: Promise<unknown>;
574+const isCurrentTask = () => store.tasks.get(id) === trackedPromise;
573575scopedChannelRuntime = await measureStartup(`channels.${channelId}.runtime`, async () =>
574576createTaskScopedChannelRuntime({
575577channelRuntime: await getChannelRuntime(),
@@ -628,7 +630,10 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage
628630abortSignal: abort.signal,
629631 log,
630632getStatus: () => getRuntime(channelId, id),
631-setStatus: (next) => setRuntimeFromTaskStatus(channelId, id, next, abort.signal),
633+setStatus: (next) =>
634+isCurrentTask()
635+ ? setRuntimeFromTaskStatus(channelId, id, next, abort.signal)
636+ : getRuntime(channelId, id),
632637 ...(channelRuntimeForTask ? { channelRuntime: channelRuntimeForTask } : {}),
633638});
634639const routeRegistry = getPluginHttpRouteRegistry?.();
@@ -641,27 +646,38 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage
641646}
642647await startAccountTask;
643648});
644-const trackedPromise = task
649+// Recovery can replace a timed-out task before the old promise settles.
650+// Only the task that still owns the store slot may write lifecycle state.
651+trackedPromise = task
645652.then(() => {
646-if (abort.signal.aborted || manuallyStopped.has(rKey)) {
653+if (abort.signal.aborted || manuallyStopped.has(rKey) || !isCurrentTask()) {
647654return;
648655}
649656const message = "channel exited without an error";
650657setRuntime(channelId, id, { accountId: id, lastError: message });
651658log.error?.(`[${id}] ${message}`);
652659})
653660.catch((err: unknown) => {
661+if (!isCurrentTask()) {
662+return;
663+}
654664const message = formatErrorMessage(err);
655665setRuntime(channelId, id, { accountId: id, lastError: message });
656666log.error?.(`[${id}] channel exited: ${message}`);
657667})
658668.then(async () => {
659669await cleanupTaskScopedApprovalRuntime("channel cleanup failed");
670+if (!isCurrentTask()) {
671+return;
672+}
660673setStoppedRuntime(channelId, id, {
661674lastStopAt: Date.now(),
662675});
663676})
664677.then(async () => {
678+if (!isCurrentTask()) {
679+return;
680+}
665681if (manuallyStopped.has(rKey)) {
666682recoveryStopTimedOut.delete(rKey);
667683recoveryStartRequested.delete(rKey);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。