fix(twitch): clear status after startup failures · openclaw/openclaw@f836934
vincentkoc
·
2026-06-17
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | // Twitch tests cover plugin.lifecycle plugin behavior. |
2 | 2 | import { |
3 | 3 | createStartAccountContext, |
| 4 | +expectLifecyclePatch, |
4 | 5 | expectStopPendingUntilAbort, |
5 | 6 | startAccountAndTrackLifecycle, |
6 | 7 | waitForStartedMocks, |
7 | 8 | } from "openclaw/plugin-sdk/channel-test-helpers"; |
| 9 | +import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/status-helpers"; |
8 | 10 | import { afterEach, describe, expect, it, vi } from "vitest"; |
9 | 11 | import type { TwitchAccountConfig } from "./types.js"; |
10 | 12 | |
@@ -84,4 +86,20 @@ describe("twitch startAccount lifecycle", () => {
|
84 | 86 | expect(hoisted.monitorTwitchProvider).toHaveBeenCalledOnce(); |
85 | 87 | expect(stop).toHaveBeenCalledOnce(); |
86 | 88 | }); |
| 89 | + |
| 90 | +it("clears running status when monitor startup fails", async () => { |
| 91 | +hoisted.monitorTwitchProvider.mockRejectedValue(new Error("irc join failed")); |
| 92 | +const patches: ChannelAccountSnapshot[] = []; |
| 93 | + |
| 94 | +const task = requireStartAccount()( |
| 95 | +createStartAccountContext({ |
| 96 | +account: buildAccount(), |
| 97 | +statusPatchSink: (next) => patches.push({ ...next }), |
| 98 | +}), |
| 99 | +); |
| 100 | + |
| 101 | +await expect(task).rejects.toThrow("irc join failed"); |
| 102 | +expectLifecyclePatch(patches, { running: true }); |
| 103 | +expectLifecyclePatch(patches, { running: false }); |
| 104 | +}); |
87 | 105 | }); |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -186,20 +186,29 @@ export const twitchPlugin: ChannelPlugin<ResolvedTwitchAccount> =
|
186 | 186 | // Keep startAccount pending until abort fires; otherwise the channel |
187 | 187 | // supervisor reads the settled task as `channel exited without an |
188 | 188 | // error` and triggers a restart loop. See #60071. |
189 | | -await runStoppablePassiveMonitor({ |
190 | | -abortSignal: ctx.abortSignal, |
191 | | -start: async () => { |
192 | | -// Lazy import: the monitor pulls the reply pipeline; avoid ESM init cycles. |
193 | | -const { monitorTwitchProvider } = await import("./monitor.js"); |
194 | | -return monitorTwitchProvider({ |
195 | | - account, |
196 | | - accountId, |
197 | | -config: ctx.cfg, |
198 | | -runtime: ctx.runtime, |
199 | | -abortSignal: ctx.abortSignal, |
200 | | -}); |
201 | | -}, |
202 | | -}); |
| 189 | +try { |
| 190 | +await runStoppablePassiveMonitor({ |
| 191 | +abortSignal: ctx.abortSignal, |
| 192 | +start: async () => { |
| 193 | +// Lazy import: the monitor pulls the reply pipeline; avoid ESM init cycles. |
| 194 | +const { monitorTwitchProvider } = await import("./monitor.js"); |
| 195 | +return monitorTwitchProvider({ |
| 196 | + account, |
| 197 | + accountId, |
| 198 | +config: ctx.cfg, |
| 199 | +runtime: ctx.runtime, |
| 200 | +abortSignal: ctx.abortSignal, |
| 201 | +}); |
| 202 | +}, |
| 203 | +}); |
| 204 | +} catch (error) { |
| 205 | +ctx.setStatus?.({ |
| 206 | + accountId, |
| 207 | +running: false, |
| 208 | +lastStopAt: Date.now(), |
| 209 | +}); |
| 210 | +throw error; |
| 211 | +} |
203 | 212 | }, |
204 | 213 | stopAccount: async (ctx): Promise<void> => { |
205 | 214 | const account = ctx.account; |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。