fix: exclude archived Buzz rooms from peer snapshots

This commit is contained in:
Shakker
2026-07-31 12:04:48 +01:00
parent 8f3c611951
commit 429e83bd23
4 changed files with 65 additions and 24 deletions

View File

@@ -194,6 +194,7 @@ describe("Buzz directory state", () => {
expect(state.activeRoomIds()).toEqual([]);
expect(state.isRoomArchived(ROOM_ID)).toBe(true);
expect(state.listPeers({})).toEqual([]);
expect(state.listGroups({})).toEqual([]);
expect(state.listGroupMembers({ groupId: ROOM_ID })).toEqual([]);
@@ -213,6 +214,7 @@ describe("Buzz directory state", () => {
expect(state.activeRoomIds()).toEqual([ROOM_ID]);
expect(state.isRoomArchived(ROOM_ID)).toBe(false);
expect(state.listPeers({})).not.toEqual([]);
expect(state.listGroups({})).toEqual([
expect.objectContaining({ id: `buzz:${ROOM_ID}`, name: "Restored room" }),
]);

View File

@@ -278,7 +278,11 @@ export class BuzzDirectoryState {
listPeers(params: { query?: string | null; limit?: number | null }): ChannelDirectoryEntry[] {
const peers = new Set<string>();
for (const membership of this.#memberships.values()) {
for (const roomId of this.activeRoomIds()) {
const membership = this.#memberships.get(roomId);
if (!membership) {
continue;
}
for (const publicKey of membership.members) {
if (publicKey !== this.#publicKey) {
peers.add(publicKey);

View File

@@ -7,6 +7,7 @@ const relayMocks = vi.hoisted(() => ({
close: vi.fn(),
connect: vi.fn(async () => {}),
filters: [] as Filter[],
roomArchived: false,
send: vi.fn(async () => {}),
subscribe: vi.fn(),
}));
@@ -83,6 +84,7 @@ describe("Buzz live directory", () => {
beforeEach(() => {
vi.clearAllMocks();
relayMocks.filters.length = 0;
relayMocks.roomArchived = false;
gatewayMocks.activeBus = undefined;
vi.stubGlobal(
"fetch",
@@ -122,6 +124,7 @@ describe("Buzz live directory", () => {
tags: [
["d", ROOM_ID],
["name", "Engineering"],
...(relayMocks.roomArchived ? [["archived", "true"]] : []),
],
}),
);
@@ -173,13 +176,13 @@ describe("Buzz live directory", () => {
expect(relayMocks.filters).toEqual([
{
kinds: [39_002],
kinds: [39_000],
authors: [RELAY_PUBLIC_KEY],
"#d": [ROOM_ID],
limit: 1,
},
{
kinds: [39_000],
kinds: [39_002],
authors: [RELAY_PUBLIC_KEY],
"#d": [ROOM_ID],
limit: 1,
@@ -190,6 +193,37 @@ describe("Buzz live directory", () => {
expect(relayMocks.close).toHaveBeenCalledOnce();
});
it("does not load peers or memberships from archived rooms", async () => {
relayMocks.roomArchived = true;
const { listBuzzDirectoryPeersLive } = await import("./directory.js");
const cfg = {
channels: {
buzz: {
relayUrl: "wss://buzz.example.com",
privateKey: PRIVATE_KEY,
groups: { [ROOM_ID]: {} },
},
},
} as unknown as OpenClawConfig;
await expect(
listBuzzDirectoryPeersLive({
cfg,
accountId: "default",
}),
).resolves.toEqual([]);
expect(relayMocks.filters).toEqual([
{
kinds: [39_000],
authors: [RELAY_PUBLIC_KEY],
"#d": [ROOM_ID],
limit: 1,
},
{ kinds: [0], authors: [BOT_PUBLIC_KEY], limit: 1 },
]);
});
it("refreshes only room listings when an active bus already owns directory state", async () => {
const refreshDirectory = vi.fn(async () => {});
const self = vi.fn(() => ({ kind: "user", id: BOT_PUBLIC_KEY, name: "OpenClaw" }));

View File

@@ -68,29 +68,30 @@ async function loadBuzzDirectoryState(
signal: timeoutSignal,
});
try {
await queryBuzzDirectoryRooms({
relay,
relayPublicKey,
state: configured.state,
channelIds: configured.channelIds,
signal: timeoutSignal,
});
const activeChannelIds = configured.state.activeRoomIds();
configured.state.replaceMemberships(
await queryBuzzRoomMemberships({
relay,
relayPublicKey,
channelIds: configured.channelIds,
signal: timeoutSignal,
}),
activeChannelIds.length > 0
? await queryBuzzRoomMemberships({
relay,
relayPublicKey,
channelIds: activeChannelIds,
signal: timeoutSignal,
})
: new Map(),
);
await Promise.all([
queryBuzzDirectoryRooms({
relay,
relayPublicKey,
state: configured.state,
channelIds: configured.channelIds,
signal: timeoutSignal,
}),
queryBuzzDirectoryProfiles({
relay,
state: configured.state,
publicKeys: configured.state.profilePublicKeys(),
signal: timeoutSignal,
}),
]);
await queryBuzzDirectoryProfiles({
relay,
state: configured.state,
publicKeys: configured.state.profilePublicKeys(),
signal: timeoutSignal,
});
return configured.state;
} finally {
relay.close();