




















@@ -146,62 +146,67 @@ export async function startClickClackGatewayAccount(
146146});
147147let afterCursor = "";
148148let initialized = false;
149-while (!ctx.abortSignal.aborted) {
150-const backlog = await client.events(workspaceId, afterCursor);
151-if (!initialized) {
152-// First pass establishes the cursor without replaying historical backlog
153-// into fresh gateway sessions.
154-for (const event of backlog) {
155-afterCursor = event.cursor || afterCursor;
156-}
157-initialized = true;
158-} else {
159-for (const event of backlog) {
160-afterCursor = event.cursor || afterCursor;
161-await processEvent({
162- account,
163-config: ctx.cfg,
164- client,
165- event,
166-botUserId: account.botUserId,
167-});
168-}
169-}
170-const socket = client.websocket(workspaceId, afterCursor);
171-await new Promise<void>((resolve, reject) => {
172-const abort = () => {
173-socket.close();
174-resolve();
175-};
176-ctx.abortSignal.addEventListener("abort", abort, { once: true });
177-socket.on("message", (data) => {
178-void (async () => {
179-const event = parseSocketEvent(data);
180-if (!event) {
181-ctx.log?.warn?.(`[${account.accountId}] skipped malformed ClickClack websocket event`);
182-return;
183-}
149+try {
150+while (!ctx.abortSignal.aborted) {
151+const backlog = await client.events(workspaceId, afterCursor);
152+if (!initialized) {
153+// First pass establishes the cursor without replaying historical backlog
154+// into fresh gateway sessions.
155+for (const event of backlog) {
156+afterCursor = event.cursor || afterCursor;
157+}
158+initialized = true;
159+} else {
160+for (const event of backlog) {
184161afterCursor = event.cursor || afterCursor;
185162await processEvent({
186163 account,
187164config: ctx.cfg,
188165 client,
189166 event,
190-botUserId: account.botUserId ?? "",
167+botUserId: account.botUserId,
191168});
192-})().catch(reject);
193-});
194-socket.on("close", () => {
195-ctx.abortSignal.removeEventListener("abort", abort);
196-resolve();
197-});
198-socket.on("error", reject);
199-});
200-if (!ctx.abortSignal.aborted) {
201-await new Promise((resolve) => {
202-setTimeout(resolve, account.reconnectMs);
169+}
170+}
171+const socket = client.websocket(workspaceId, afterCursor);
172+await new Promise<void>((resolve, reject) => {
173+const abort = () => {
174+socket.close();
175+resolve();
176+};
177+ctx.abortSignal.addEventListener("abort", abort, { once: true });
178+socket.on("message", (data) => {
179+void (async () => {
180+const event = parseSocketEvent(data);
181+if (!event) {
182+ctx.log?.warn?.(
183+`[${account.accountId}] skipped malformed ClickClack websocket event`,
184+);
185+return;
186+}
187+afterCursor = event.cursor || afterCursor;
188+await processEvent({
189+ account,
190+config: ctx.cfg,
191+ client,
192+ event,
193+botUserId: account.botUserId ?? "",
194+});
195+})().catch(reject);
196+});
197+socket.on("close", () => {
198+ctx.abortSignal.removeEventListener("abort", abort);
199+resolve();
200+});
201+socket.on("error", reject);
203202});
203+if (!ctx.abortSignal.aborted) {
204+await new Promise((resolve) => {
205+setTimeout(resolve, account.reconnectMs);
206+});
207+}
204208}
209+} finally {
210+ctx.setStatus({ accountId: account.accountId, running: false });
205211}
206-ctx.setStatus({ accountId: account.accountId, running: false });
207212}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。