

























@@ -419,6 +419,59 @@ describe("server-channels auto restart", () => {
419419expect(hoisted.sleepWithAbort).not.toHaveBeenCalled();
420420});
421421422+it("consumes startup failures during immediate recovery restart", async () => {
423+const unhandledRejection = vi.fn();
424+process.on("unhandledRejection", unhandledRejection);
425+try {
426+const releaseFirstTask = createDeferred();
427+let isConfiguredCalls = 0;
428+const startAccount = vi.fn(
429+async ({ abortSignal }: { abortSignal: AbortSignal }) =>
430+await new Promise<void>((resolve) => {
431+abortSignal.addEventListener("abort", () => {}, { once: true });
432+void releaseFirstTask.promise.then(resolve);
433+}),
434+);
435+installTestRegistry(
436+createTestPlugin({
437+ startAccount,
438+isConfigured: () => {
439+isConfiguredCalls += 1;
440+if (isConfiguredCalls > 1) {
441+throw new Error("restart config missing");
442+}
443+return true;
444+},
445+}),
446+);
447+const manager = createManager();
448+449+await manager.startChannels();
450+const recoveryStopTask = manager.stopChannel("discord", DEFAULT_ACCOUNT_ID, {
451+manual: false,
452+});
453+await vi.advanceTimersByTimeAsync(5_000);
454+await recoveryStopTask;
455+456+releaseFirstTask.resolve();
457+await waitForMicrotaskCondition(
458+() =>
459+manager.getRuntimeSnapshot().channelAccounts.discord?.[DEFAULT_ACCOUNT_ID]?.lastError ===
460+"restart config missing",
461+"expected immediate recovery restart failure to be recorded",
462+);
463+await flushMicrotasks();
464+465+const account = manager.getRuntimeSnapshot().channelAccounts.discord?.[DEFAULT_ACCOUNT_ID];
466+expect(startAccount).toHaveBeenCalledTimes(1);
467+expect(account?.running).toBe(false);
468+expect(account?.restartPending).toBe(false);
469+expect(unhandledRejection).not.toHaveBeenCalled();
470+} finally {
471+process.off("unhandledRejection", unhandledRejection);
472+}
473+});
474+422475it("lets manual stops cancel recovery restart after recovery stop times out", async () => {
423476const releaseFirstTask = createDeferred();
424477const startAccount = vi.fn(
@@ -455,6 +508,15 @@ describe("server-channels auto restart", () => {
455508expect(account?.restartPending).toBe(false);
456509expect(manager.isManuallyStopped("discord", DEFAULT_ACCOUNT_ID)).toBe(true);
457510expect(hoisted.sleepWithAbort).not.toHaveBeenCalled();
511+512+await manager.startChannel("discord", DEFAULT_ACCOUNT_ID);
513+await waitForMicrotaskCondition(
514+() => hoisted.sleepWithAbort.mock.calls.length === 1,
515+"expected later ordinary exit to use restart backoff",
516+);
517+518+expect(startAccount).toHaveBeenCalledTimes(2);
519+expect(hoisted.sleepWithAbort.mock.calls[0]?.[0]).toBe(10);
458520});
459521460522it("marks enabled/configured when account descriptors omit them", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。