mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 18:21:34 +00:00
fix: use real Buzz relay EOSE
This commit is contained in:
32
extensions/buzz/src/relay-subscription.test.ts
Normal file
32
extensions/buzz/src/relay-subscription.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { Filter, Relay } from "nostr-tools";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { openBuzzRelaySubscription } from "./relay-subscription.js";
|
||||
|
||||
describe("openBuzzRelaySubscription", () => {
|
||||
it("sends an explicit REQ without synthesizing EOSE", async () => {
|
||||
vi.useFakeTimers();
|
||||
const oneose = vi.fn();
|
||||
const subscription = {
|
||||
id: "sub:1",
|
||||
close: vi.fn(),
|
||||
} as unknown as ReturnType<Relay["prepareSubscription"]>;
|
||||
const relay = {
|
||||
idleSince: Date.now(),
|
||||
ongoingOperations: 0,
|
||||
prepareSubscription: vi.fn(() => subscription),
|
||||
send: vi.fn(async () => {}),
|
||||
} as unknown as Relay;
|
||||
const filters: Filter[] = [{ kinds: [0], authors: ["a".repeat(64)] }];
|
||||
|
||||
const opened = openBuzzRelaySubscription(relay, filters, { oneose });
|
||||
await vi.advanceTimersByTimeAsync(5_000);
|
||||
|
||||
expect(opened).toBe(subscription);
|
||||
expect(relay.prepareSubscription).toHaveBeenCalledWith(filters, { oneose });
|
||||
expect(relay.send).toHaveBeenCalledWith(JSON.stringify(["REQ", "sub:1", ...filters]));
|
||||
expect(relay.ongoingOperations).toBe(1);
|
||||
expect(relay.idleSince).toBeUndefined();
|
||||
expect(oneose).not.toHaveBeenCalled();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
34
extensions/buzz/src/relay-subscription.ts
Normal file
34
extensions/buzz/src/relay-subscription.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Filter, Relay } from "nostr-tools";
|
||||
|
||||
type BuzzRelaySubscriptionParams = Omit<Parameters<Relay["prepareSubscription"]>[1], "abort">;
|
||||
|
||||
export function openBuzzRelaySubscription(
|
||||
relay: Relay,
|
||||
filters: Filter[],
|
||||
params: BuzzRelaySubscriptionParams,
|
||||
): ReturnType<Relay["prepareSubscription"]> {
|
||||
// Relay.subscribe() synthesizes EOSE after 4.4 seconds. Buzz needs the relay's
|
||||
// real EOSE before replacing or closing subscriptions, otherwise an async REQ
|
||||
// can register after CLOSE and remain orphaned on the server.
|
||||
relay.idleSince = undefined;
|
||||
relay.ongoingOperations += 1;
|
||||
|
||||
let subscription: ReturnType<Relay["prepareSubscription"]>;
|
||||
try {
|
||||
subscription = relay.prepareSubscription(filters, params);
|
||||
} catch (error) {
|
||||
relay.ongoingOperations -= 1;
|
||||
if (relay.ongoingOperations === 0) {
|
||||
relay.idleSince = Date.now();
|
||||
relay.scheduleIdleClose();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
const frame = JSON.stringify(["REQ", subscription.id, ...filters]);
|
||||
void relay.send(frame).catch((error: unknown) => {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
subscription.close(`Buzz relay subscription request failed: ${message}`);
|
||||
});
|
||||
return subscription;
|
||||
}
|
||||
Reference in New Issue
Block a user