Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
const SLACK_AUTH_ERROR_RE =
/account_inactive|invalid_auth|token_revoked|token_expired|not_authed|org_login_required|team_access_not_granted|missing_scope|cannot_find_service|invalid_token/i;
export const SLACK_SOCKET_RECONNECT_POLICY = {
initialMs: 2_000,
maxMs: 30_000,
factor: 1.8,
jitter: 0.25,
maxAttempts: 12,
} as const;
export type SlackSocketDisconnectEvent = "disconnect" | "unable_to_socket_mode_start" | "error";
type EmitterLike = {
on: (event: string, listener: (...args: unknown[]) => void) => unknown;
off: (event: string, listener: (...args: unknown[]) => void) => unknown;
};
export function getSocketEmitter(app: unknown): EmitterLike | null {
const receiver = (app as { receiver?: unknown }).receiver;
const client =
receiver && typeof receiver === "object"
? (receiver as { client?: unknown }).client
: undefined;
if (!client || typeof client !== "object") {
return null;
}
const on = (client as { on?: unknown }).on;
const off = (client as { off?: unknown }).off;
if (typeof on !== "function" || typeof off !== "function") {
return null;
}
return {
on: (event, listener) =>
(
on as (this: unknown, event: string, listener: (...args: unknown[]) => void) => unknown
).call(client, event, listener),
off: (event, listener) =>
(
off as (this: unknown, event: string, listener: (...args: unknown[]) => void) => unknown
).call(client, event, listener),
};
}
export function waitForSlackSocketDisconnect(
app: unknown,
abortSignal?: AbortSignal,
): Promise<{
event: SlackSocketDisconnectEvent;
error?: unknown;
}> {
return new Promise((resolve) => {
const emitter = getSocketEmitter(app);
if (!emitter) {
abortSignal?.addEventListener("abort", () => resolve({ event: "disconnect" }), {
once: true,
});
return;
}
const disconnectListener = () => resolveOnce({ event: "disconnect" });
const startFailListener = (error?: unknown) =>
resolveOnce({ event: "unable_to_socket_mode_start", error });
const errorListener = (error: unknown) => resolveOnce({ event: "error", error });
const abortListener = () => resolveOnce({ event: "disconnect" });
const cleanup = () => {
emitter.off("disconnected", disconnectListener);
emitter.off("unable_to_socket_mode_start", startFailListener);
emitter.off("error", errorListener);
abortSignal?.removeEventListener("abort", abortListener);
};
const resolveOnce = (value: { event: SlackSocketDisconnectEvent; error?: unknown }) => {
cleanup();
resolve(value);
};
emitter.on("disconnected", disconnectListener);
emitter.on("unable_to_socket_mode_start", startFailListener);
emitter.on("error", errorListener);
abortSignal?.addEventListener("abort", abortListener, { once: true });
});
}
/**
* Detect non-recoverable Slack API / auth errors that should NOT be retried.
* These indicate permanent credential problems (revoked bot, deactivated account, etc.)
* and retrying will never succeed — continuing to retry blocks the entire gateway.
*/
export function isNonRecoverableSlackAuthError(error: unknown): boolean {
const msg = error instanceof Error ? error.message : typeof error === "string" ? error : "";
return SLACK_AUTH_ERROR_RE.test(msg);
}
export function formatUnknownError(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
if (typeof error === "string") {
return error;
}
try {
return JSON.stringify(error);
} catch {
return "unknown error";
}
}
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-04-27)
¤
*© Formatika GbR, Deutschland