fix: add 8 s timeout + logging to actor lookup in resolveRemoteAccount
Deploy Indiekit Server / deploy (push) Successful in 1m19s
Deploy Indiekit Server / deploy (push) Successful in 1m19s
lookupWithSecurity → ctx.lookupObject had no timeout, so clicking a @mention handle for an account not in local collections could hang indefinitely or fail silently with no log entry. Now caps the lookup at 8 s and logs "Actor lookup failed" / "returned null" so server logs will show exactly why @mention lookups fail. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -219,4 +219,44 @@ for (const f of SEARCH_CANDIDATES) {
|
||||
}
|
||||
if (!searchDone) console.log(`[postinstall] ${SCRIPT}: ap-search-url-resolve — no target file found or no changes`);
|
||||
|
||||
// ── patch-ap-resolve-actor-timeout: cap actor lookup at 8 s + log failures ───
|
||||
// When Mastodon client clicks a @mention handle, /api/v1/accounts/lookup calls
|
||||
// resolveRemoteAccount → lookupWithSecurity → ctx.lookupObject (no timeout).
|
||||
// If the remote server hangs, the request hangs indefinitely. Even when it fails
|
||||
// fast, we get 404 with no log entry explaining why.
|
||||
// Fix: wrap lookupWithSecurity in an 8 s timeout; log on failure/null result.
|
||||
|
||||
const ACTOR_TIMEOUT_MARKER = "// [patch] ap-resolve-actor-timeout";
|
||||
const RESOLVE_ACCOUNT_CANDIDATES = apPath("lib/mastodon/helpers/resolve-account.js");
|
||||
|
||||
const ACTOR_TIMEOUT_OLD = ` // Use signed→unsigned fallback so servers rejecting signed GETs still resolve
|
||||
const documentLoader = await ctx.getDocumentLoader({ identifier: handle });
|
||||
const actor = await lookupWithSecurity(ctx, actorUri, { documentLoader });
|
||||
if (!actor) return null;`;
|
||||
|
||||
const ACTOR_TIMEOUT_NEW = ` // Use signed→unsigned fallback so servers rejecting signed GETs still resolve
|
||||
const documentLoader = await ctx.getDocumentLoader({ identifier: handle });
|
||||
// Timeout guard: cap actor fetch at 8 s so hung lookups fail fast. ${ACTOR_TIMEOUT_MARKER}
|
||||
const _aLookupTimeout = (p, ms = 8000) => { const t = new Promise((_, rej) => setTimeout(() => rej(new Error("actor lookup timeout")), ms)); p.catch(() => {}); return Promise.race([p, t]); }; ${ACTOR_TIMEOUT_MARKER}
|
||||
const actor = await _aLookupTimeout(lookupWithSecurity(ctx, actorUri, { documentLoader })).catch(err => { console.warn(\`[Mastodon API] Actor lookup failed for \${acct}: \${err.message}\`); return null; }); ${ACTOR_TIMEOUT_MARKER}
|
||||
if (!actor) { console.warn(\`[Mastodon API] lookupWithSecurity returned null for \${acct}\`); return null; } ${ACTOR_TIMEOUT_MARKER}`;
|
||||
|
||||
let actorTimeoutDone = false;
|
||||
for (const f of RESOLVE_ACCOUNT_CANDIDATES) {
|
||||
if (!(await fileExists(f))) continue;
|
||||
const src = await readFile(f, "utf8");
|
||||
if (src.includes(ACTOR_TIMEOUT_MARKER)) {
|
||||
console.log(`[postinstall] ${SCRIPT}: ap-resolve-actor-timeout already applied in ${f}`);
|
||||
actorTimeoutDone = true; break;
|
||||
}
|
||||
if (!src.includes(ACTOR_TIMEOUT_OLD)) {
|
||||
console.warn(`[postinstall] ${SCRIPT}: ap-resolve-actor-timeout — anchor not found in ${f}`);
|
||||
continue;
|
||||
}
|
||||
await writeFile(f, src.replace(ACTOR_TIMEOUT_OLD, ACTOR_TIMEOUT_NEW), "utf8");
|
||||
console.log(`[postinstall] ${SCRIPT}: applied ap-resolve-actor-timeout to ${f}`);
|
||||
total++; actorTimeoutDone = true; break;
|
||||
}
|
||||
if (!actorTimeoutDone) console.log(`[postinstall] ${SCRIPT}: ap-resolve-actor-timeout — no target file found or no changes`);
|
||||
|
||||
console.log(`[postinstall] ${SCRIPT}: done (${total} patch(es) applied)`);
|
||||
|
||||
Reference in New Issue
Block a user