mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
fix(lists): give slow signers room to decrypt (raise timeout budget)
Real-env console: signerStatus "present" but every block/hashtag decrypt timed out at the 15s service budget, forever, retrying every ~15s for 15+ minutes — lists never loaded. Reproduced deterministically with the channel-sim harness (latency override): with per-call latency BELOW the service budget all lists load; the instant it crosses the budget every list fails (NO) and retries forever. A nip-07 decrypt is a postMessage round-trip to the extension's single-threaded, possibly-sleeping service worker — under cold-login load real extensions take 15-25s to answer even though the crypto is instant. The earlier 6s per-call timeout was killing those in-progress decrypts. Raise the budget across blocks/hashtags/subscriptions so a slow-but- responsive signer completes instead of timing out: - service-level DECRYPT_TIMEOUT_MS 15s → 30s - per-call nip-07 decrypt timeout 6s → 25s interactive / ~10-12s background - backoff cap 30s → 60s so a persistently dead signer settles into an occasional heartbeat instead of pinning the extension every ~15s Harness: at 16s/call (previously NO across the board) blocks + subscriptions + hashtags now all decrypt (0 timeouts); healthy mode unchanged (signer-ready ~1.2s). Full unit suite green. KNOWN_BUGS #0. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
0db4f0a603
commit
38c9c52c0a
4 files changed
+47
-27
No files matched your search
@@ -46,11 +46,14 @@ const DEFAULT_VERSION = 1;
|
||||
// nip-07 extension, and the main thread can be busy connecting to relays. 6s
|
||||
// proved too aggressive on real accounts (lists timed out and showed empty);
|
||||
// 15s matches the block-list timeout and lets decryption complete under load.
|
||||
const DECRYPT_TIMEOUT_MS = 15000;
|
||||
// Generous decrypt budget: real extensions can take 15-25s to answer a nip-07
|
||||
// decrypt under cold-login load even though the crypto is instant. A tighter
|
||||
// budget times out mid-flight and retries forever (KNOWN_BUGS #0).
|
||||
const DECRYPT_TIMEOUT_MS = 30000;
|
||||
// PERF: Reduced from 3s to 1.5s — extensions that already granted permission
|
||||
// should recover near-instantly. Shorter delay speeds up the login path.
|
||||
const DECRYPT_RETRY_DELAY_MS = NETWORK_RETRY_DELAY_MS;
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 30000;
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 60000;
|
||||
|
||||
// Transient decrypt failures that must RETRY in the background rather than give
|
||||
// up: our own timeout, a severed nip-07 message port ("message channel closed"),
|
||||
@@ -1130,11 +1133,11 @@ class HashtagPreferencesService {
|
||||
sources.set(scheme, source);
|
||||
};
|
||||
|
||||
// PERF: Reduced no-prompt timeout from 8s to 5s — the signer readiness
|
||||
// gate guarantees the extension is ready before decryption starts, so
|
||||
// decrypt calls should complete within 1-2s. 5s accommodates slow
|
||||
// extensions while still failing fast for scheme fallback.
|
||||
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 6000 : SHORT_TIMEOUT_MS;
|
||||
// Per-call nip-07 decrypt budget. A short value kills in-progress decrypts
|
||||
// on slow extensions (15-25s under cold-login load), so the list never
|
||||
// decrypts and retries forever. Give the interactive call real room; the
|
||||
// background refresh stays tighter for fast scheme fallback.
|
||||
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 25000 : 10000;
|
||||
const signerDecryptOptions = {
|
||||
priority: NIP07_PRIORITY.NORMAL,
|
||||
timeoutMs: nip07DecryptTimeoutMs,
|
||||
|
||||
+11
-8
@@ -53,12 +53,15 @@ const SUBSCRIPTION_SET_KIND =
|
||||
// so decryption should succeed within 2-3s. 6s is generous enough for slow
|
||||
// relays while still failing fast enough for the scheme fallback to try the
|
||||
// next decryption method without stalling the login path.
|
||||
const DECRYPT_TIMEOUT_MS = 15000;
|
||||
// Generous decrypt budget: real extensions can take 15-25s to answer a nip-07
|
||||
// decrypt under cold-login load even though the crypto is instant. A tighter
|
||||
// budget times out mid-flight and retries forever (KNOWN_BUGS #0).
|
||||
const DECRYPT_TIMEOUT_MS = 30000;
|
||||
// PERF: Reduced from 3s to 1.5s — extensions that already granted permission
|
||||
// should recover near-instantly. The shorter delay prevents unnecessary wait
|
||||
// time during the critical login path when the first decrypt attempt fails.
|
||||
const DECRYPT_RETRY_DELAY_MS = 1500;
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 30000;
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 60000;
|
||||
|
||||
// Transient decrypt failures that must RETRY rather than give up: our own
|
||||
// timeout, a severed nip-07 message port ("message channel closed"), and the
|
||||
@@ -1240,13 +1243,13 @@ class SubscriptionsManager {
|
||||
decryptors.set(scheme, handler);
|
||||
};
|
||||
|
||||
// PERF: Reduced no-prompt timeout from 8s to 5s — the signer readiness
|
||||
// gate now guarantees the extension is ready before decryption starts, so
|
||||
// decrypt calls should complete within 1-2s. 5s accommodates slow
|
||||
// extensions while still failing fast enough for scheme fallback.
|
||||
// Per-call nip-07 decrypt budget. A short value kills in-progress decrypts
|
||||
// on slow extensions (15-25s under cold-login load), so the list never
|
||||
// decrypts and retries forever. Give the interactive call real room; the
|
||||
// background refresh stays tighter for fast scheme fallback.
|
||||
const nip07DecryptTimeoutMs = allowPermissionPrompt
|
||||
? 6000
|
||||
: SHORT_TIMEOUT_MS;
|
||||
? 25000
|
||||
: 10000;
|
||||
const signerDecryptOptions = {
|
||||
priority: NIP07_PRIORITY.NORMAL,
|
||||
timeoutMs: nip07DecryptTimeoutMs,
|
||||
|
||||
+19
-11
@@ -89,12 +89,21 @@ const FAST_BLOCKLIST_RELAY_LIMIT = 3;
|
||||
const FAST_BLOCKLIST_TIMEOUT_MS = 2500;
|
||||
const BACKGROUND_BLOCKLIST_TIMEOUT_MS = 6000;
|
||||
const MAX_BACKGROUND_BLOCKLIST_RELAY_LIMIT = 24;
|
||||
// Keep interactive decrypt timeout above extension retry timeout window.
|
||||
const DECRYPT_TIMEOUT_MS = Math.max(STANDARD_TIMEOUT_MS, 15000);
|
||||
const BACKGROUND_DECRYPT_TIMEOUT_MS = 8000;
|
||||
// Decrypt timeout budget. A nip-07 decrypt is a postMessage round-trip to the
|
||||
// extension's (single-threaded, possibly sleeping) service worker — under
|
||||
// cold-login load real extensions can take 15-25s to answer even though the
|
||||
// crypto itself is instant. The harness (scripts/perf/nip07-channel-sim.mjs)
|
||||
// shows lists fail to load the moment per-call latency crosses this budget, so
|
||||
// keep it generous (30s) to give a slow-but-responsive signer room to complete
|
||||
// rather than timing out and retrying forever (KNOWN_BUGS #0).
|
||||
const DECRYPT_TIMEOUT_MS = Math.max(STANDARD_TIMEOUT_MS, 30000);
|
||||
const BACKGROUND_DECRYPT_TIMEOUT_MS = 12000;
|
||||
// PERF: Reduced from 10s to 3s for faster recovery during login.
|
||||
const DECRYPT_RETRY_DELAY_MS = 3000;
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 30000;
|
||||
// Cap the exponential backoff well above the decrypt budget so a persistently
|
||||
// unresponsive signer settles into an occasional heartbeat instead of pinning
|
||||
// the extension/CPU every ~15s indefinitely.
|
||||
const MAX_DECRYPT_RETRY_DELAY_MS = 60000;
|
||||
|
||||
// Transient decrypt failures that must KEEP the stale list and RETRY in the
|
||||
// background (the channel/extension recovers shortly), rather than giving up
|
||||
@@ -982,13 +991,12 @@ class UserBlockListManager {
|
||||
: allowPermissionPrompt
|
||||
? DECRYPT_TIMEOUT_MS
|
||||
: BACKGROUND_DECRYPT_TIMEOUT_MS;
|
||||
// A healthy nip04/nip44 decrypt is local crypto (~1s). The login-time value
|
||||
// was 15s purely to tolerate a slow first-grant prompt — but permissions are
|
||||
// pre-granted by the readiness gate, so a 15s timeout just monopolizes one of
|
||||
// the two NIP-07 queue slots on a doomed call, starving the gate (real-env
|
||||
// ~48s signer-ready — KNOWN_BUGS #0). 6s still tolerates a slow extension
|
||||
// while freeing the slot ~2.5x faster.
|
||||
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 6000 : 6000;
|
||||
// Per-call nip-07 decrypt budget. A 6s value (tried earlier) killed
|
||||
// in-progress decrypts on slow extensions that legitimately need 15-25s to
|
||||
// answer under cold-login load, so the list never decrypted and retried
|
||||
// forever. Give the call real room (interactive 25s, background 12s) — it
|
||||
// sits below the service-level DECRYPT_TIMEOUT_MS backstop.
|
||||
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 25000 : 12000;
|
||||
const emitStatus = (detail) => {
|
||||
if (!detail || typeof detail !== "object") {
|
||||
return;
|
||||
|
||||
@@ -54,7 +54,13 @@ const MODES = {
|
||||
dead: { latency: 400, maxInflight: 1, dropCooldown: 10 ** 9 },
|
||||
};
|
||||
const HEALTHY = MODES.healthy;
|
||||
const TARGET = MODES[MODE] || MODES.overload;
|
||||
const TARGET = { ...(MODES[MODE] || MODES.overload) };
|
||||
// Allow overriding the per-call latency to model a genuinely slow extension
|
||||
// (the real-env case: signer present but every decrypt sits in the nip-07
|
||||
// queue long enough to blow the 15s service timeout).
|
||||
if (Number.isFinite(Number(process.env.LATENCY_MS))) {
|
||||
TARGET.latency = Number(process.env.LATENCY_MS);
|
||||
}
|
||||
|
||||
const USER_SK = Uint8Array.from(Buffer.from("11".repeat(32), "hex"));
|
||||
const USER_PK = getPublicKey(USER_SK);
|
||||
|
||||
Reference in new issue
Block a user