Files
buzz/desktop/src/shared/api/relayGateBoundary.ts
Will Pfleger 258cc92064 fix(desktop): survive degraded networks with rate-limit-aware relay client (#2197)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw <4a1bfa0013bc6d14a8d600d8bf6392efefbd2a26ac3c96c9b2a106b0d12297ca@sprout-oss.stage.blox.sqprod.co>
2026-07-21 12:18:20 -04:00

57 lines
1.8 KiB
TypeScript

/**
* Gate-aware relay operation boundaries.
*
* History REQ operations are issued here rather than inline in RelayClient so
* the gate-await + op-timeout pattern lives in one place and the op timeout
* budget starts only after the rate-limit window has cleared.
*/
import { waitForRateLimit } from "@/shared/api/relayRateLimitGate";
import type {
RelaySubscription,
RelaySubscriptionFilter,
} from "@/shared/api/relayClientShared";
import type { RelayEvent } from "@/shared/api/types";
/**
* Issue a history REQ on `filter`, waiting for any active rate-limit gate
* before starting the subscription so the op timeout begins only after
* back-pressure has cleared.
*/
export async function requestHistoryGated(
subscriptions: Map<string, RelaySubscription>,
sendRaw: (payload: unknown[]) => Promise<void>,
closeSubscription: (subId: string) => Promise<void>,
filter: RelaySubscriptionFilter,
historyTimeoutMs: number,
): Promise<RelayEvent[]> {
// Await the gate before issuing REQ; op timeout starts after the wait.
await waitForRateLimit();
return new Promise<RelayEvent[]>((resolve, reject) => {
const subId = `history-${crypto.randomUUID()}`;
const timeout = window.setTimeout(() => {
subscriptions.delete(subId);
void closeSubscription(subId);
reject(new Error("Timed out while loading channel history."));
}, historyTimeoutMs);
subscriptions.set(subId, {
mode: "history",
events: [],
resolve,
reject,
timeout,
});
void sendRaw(["REQ", subId, filter]).catch((error) => {
window.clearTimeout(timeout);
subscriptions.delete(subId);
reject(
error instanceof Error
? error
: new Error("Failed to request channel history."),
);
});
});
}