fix: provisioner matrix login retries through M_LIMIT_EXCEEDED instead of failing boot

Rapid deploy restarts exhausted the homeserver's per-account login rate
limit; bootstrap now backs off 5s/15s/45s/90s on 429 before giving up.
This commit is contained in:
glass beadian 2026-10-14 13:55:05 +00:00
parent 71ccc1db75
commit d87c4e99e6

View file

@ -26,13 +26,29 @@ class NullProvisioner implements ProvisionerPort {
let cachedClient: MatrixHttpClient | null = null;
/** Login is rate-limited by the homeserver per account; a deploy restart can
* trip it (M_LIMIT_EXCEEDED). Retry with backoff instead of failing boot. */
const LOGIN_RETRY_DELAYS_MS = [5_000, 15_000, 45_000, 90_000];
/** Lazily logs in the provisioner bot (once per process) and wraps it. */
async function buildProvisioner(logger?: Logger): Promise<ProvisionerPort> {
const config = loadProvisionerConfig();
if (config === null) return new NullProvisioner();
if (cachedClient === null) {
cachedClient = new MatrixHttpClient(config);
await cachedClient.login();
for (let attempt = 0; ; attempt++) {
try {
await cachedClient.login();
break;
} catch (error) {
const isLast = attempt >= LOGIN_RETRY_DELAYS_MS.length;
const rateLimited = /M_LIMIT_EXCEEDED|HTTP 429/.test(error instanceof Error ? error.message : String(error));
if (isLast || !rateLimited) throw error;
const wait = LOGIN_RETRY_DELAYS_MS[attempt] ?? 90_000;
logger?.warn(`provisioner matrix login rate-limited; retry ${attempt + 1} in ${Math.round(wait / 1000)}s`);
await new Promise((resolve) => setTimeout(resolve, wait));
}
}
}
return new MatrixProvisioner({ matrix: cachedClient, logger });
}