mirror of https://github.com/openclaw/openclaw.git
86 lines
2.9 KiB
TypeScript
86 lines
2.9 KiB
TypeScript
import type { RuntimeEnv } from "../runtime-api.js";
|
|
import { waitForAbortableDelay } from "./async.js";
|
|
import { fetchBotIdentityForMonitor, type FeishuMonitorBotIdentity } from "./monitor.startup.js";
|
|
import { botNames, botOpenIds } from "./monitor.state.js";
|
|
import type { ResolvedFeishuAccount } from "./types.js";
|
|
|
|
// Delays must be >= PROBE_ERROR_TTL_MS (60s) so each retry makes a real network request
|
|
// instead of silently hitting the probe error cache.
|
|
export const BOT_IDENTITY_RETRY_DELAYS_MS = [60_000, 120_000, 300_000, 600_000, 900_000];
|
|
|
|
export function applyBotIdentityState(
|
|
accountId: string,
|
|
identity: FeishuMonitorBotIdentity,
|
|
): { botOpenId?: string; botName?: string } {
|
|
const botOpenId = identity.botOpenId?.trim() || undefined;
|
|
const botName = identity.botName?.trim() || undefined;
|
|
|
|
botOpenIds.set(accountId, botOpenId ?? "");
|
|
if (botName) {
|
|
botNames.set(accountId, botName);
|
|
} else {
|
|
botNames.delete(accountId);
|
|
}
|
|
|
|
return { botOpenId, botName };
|
|
}
|
|
|
|
async function retryBotIdentityProbe(
|
|
account: ResolvedFeishuAccount,
|
|
accountId: string,
|
|
runtime: RuntimeEnv | undefined,
|
|
abortSignal: AbortSignal | undefined,
|
|
): Promise<void> {
|
|
const log = runtime?.log ?? console.log;
|
|
const error = runtime?.error ?? console.error;
|
|
|
|
for (let i = 0; i < BOT_IDENTITY_RETRY_DELAYS_MS.length; i += 1) {
|
|
if (abortSignal?.aborted) {
|
|
return;
|
|
}
|
|
|
|
const delayElapsed = await waitForAbortableDelay(BOT_IDENTITY_RETRY_DELAYS_MS[i], abortSignal);
|
|
if (!delayElapsed) {
|
|
return;
|
|
}
|
|
|
|
const identity = await fetchBotIdentityForMonitor(account, { runtime, abortSignal });
|
|
const resolved = applyBotIdentityState(accountId, identity);
|
|
if (resolved.botOpenId) {
|
|
log(
|
|
`feishu[${accountId}]: bot open_id recovered via background retry: ${resolved.botOpenId}`,
|
|
);
|
|
return;
|
|
}
|
|
|
|
const nextDelay = BOT_IDENTITY_RETRY_DELAYS_MS[i + 1];
|
|
error(
|
|
`feishu[${accountId}]: bot identity background retry ${i + 1}/${BOT_IDENTITY_RETRY_DELAYS_MS.length} failed` +
|
|
(nextDelay ? `; next attempt in ${nextDelay / 1000}s` : ""),
|
|
);
|
|
}
|
|
|
|
error(
|
|
`feishu[${accountId}]: bot identity background retry exhausted; requireMention group messages may be skipped until restart`,
|
|
);
|
|
}
|
|
|
|
export function startBotIdentityRecovery(params: {
|
|
account: ResolvedFeishuAccount;
|
|
accountId: string;
|
|
runtime?: RuntimeEnv;
|
|
abortSignal?: AbortSignal;
|
|
}): void {
|
|
const { account, accountId, runtime, abortSignal } = params;
|
|
const log = runtime?.log ?? console.log;
|
|
|
|
log(
|
|
`feishu[${accountId}]: bot open_id unknown; starting background retry (delays: ${BOT_IDENTITY_RETRY_DELAYS_MS.map((delay) => `${delay / 1000}s`).join(", ")})`,
|
|
);
|
|
log(
|
|
`feishu[${accountId}]: requireMention group messages stay gated until bot identity recovery succeeds`,
|
|
);
|
|
|
|
void retryBotIdentityProbe(account, accountId, runtime, abortSignal);
|
|
}
|