Files
bitvid/tests/admin-list-batched-fetch.test.mjs
thePR0M3TH3ANandClaude Opus 4.8 a8e9f5202a adminLists: batch community-blacklist fetch (kill cold-start kind-30000 storm)
Cold-start fired one kind-30000 REQ per community-blacklist curator
(loadCommunityBlacklistEntries did Promise.all over references, each a
fetchLatestListEvent) — ~28-32 parallel REQs that dominated the login
relay-REQ spike and starved the feed.

A Nostr filter ORs `authors` and `#d`, so all curators collapse into ONE
batched REQ. New js/adminListBatch.js (pure, mutation-tested):
buildBatchedReferenceFilter + selectNewestEventsForReferences (newest per
author:d-tag, discards author×d-tag cross-products) +
fetchBatchedReferenceEvents (routes through the subscription manager's
list — health-gated/timeout-bounded, not raw pool). Helpers extracted to
their own module so adminListStore stays under its size cap.

Best-effort: on batch failure we return nothing and the cached admin
state carries over (readCachedAdminState).

Addresses pre-launch TODO #9 (cold-login REQ storm). Tests + mutation-
verified (newest selection, cross-product discard). 1249/1250 unit
(known UploadModal flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 18:47:00 -04:00

74 lines
2.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Batching the community-blacklist curator fetch into a single multi-author REQ
// (instead of one kind-30000 REQ per curator — the cold-start relay storm).
// Tests the pure filter-builder + result-selector.
import assert from "node:assert/strict";
import test from "node:test";
import {
buildBatchedReferenceFilter,
selectNewestEventsForReferences,
} from "../js/adminListBatch.js";
const A = "a".repeat(64);
const B = "b".repeat(64);
function evt({ id, pubkey, d, created_at }) {
return { id, pubkey, created_at, tags: [["d", d]] };
}
test("builds one filter with all unique authors + d-tags", () => {
const filter = buildBatchedReferenceFilter([
{ authorHex: A, dTag: "community:blacklist" },
{ authorHex: B, dTag: "community:blacklist" },
{ authorHex: A, dTag: "community:blacklist" }, // dup
]);
assert.deepEqual(filter.kinds, [30000]);
assert.deepEqual(filter.authors.sort(), [A, B]);
assert.deepEqual(filter["#d"], ["community:blacklist"]);
});
test("returns null when there are no usable references", () => {
assert.equal(buildBatchedReferenceFilter([]), null);
assert.equal(buildBatchedReferenceFilter([{ authorHex: "", dTag: "" }]), null);
});
test("selects the newest event per (author, d-tag) reference", () => {
const references = [
{ authorHex: A, dTag: "list-1" },
{ authorHex: B, dTag: "list-1" },
];
const events = [
evt({ id: "a-old", pubkey: A, d: "list-1", created_at: 100 }),
evt({ id: "a-new", pubkey: A, d: "list-1", created_at: 200 }),
evt({ id: "b-only", pubkey: B, d: "list-1", created_at: 50 }),
];
const matched = selectNewestEventsForReferences(events, references);
assert.deepEqual(matched.map((e) => e.id), ["a-new", "b-only"]);
});
test("discards cross-product events that aren't real references", () => {
// The batched filter (authors A,B × d-tags d1,d2) can return (A,d2) even
// though only (A,d1) and (B,d2) were requested. Those must be dropped.
const references = [
{ authorHex: A, dTag: "d1" },
{ authorHex: B, dTag: "d2" },
];
const events = [
evt({ id: "a-d1", pubkey: A, d: "d1", created_at: 10 }),
evt({ id: "a-d2-crossproduct", pubkey: A, d: "d2", created_at: 99 }),
evt({ id: "b-d2", pubkey: B, d: "d2", created_at: 10 }),
];
const matched = selectNewestEventsForReferences(events, references);
assert.deepEqual(matched.map((e) => e.id).sort(), ["a-d1", "b-d2"]);
});
test("tie-break on created_at uses higher event id (deterministic)", () => {
const references = [{ authorHex: A, dTag: "d1" }];
const events = [
evt({ id: "id-aaa", pubkey: A, d: "d1", created_at: 100 }),
evt({ id: "id-zzz", pubkey: A, d: "d1", created_at: 100 }),
];
const matched = selectNewestEventsForReferences(events, references);
assert.deepEqual(matched.map((e) => e.id), ["id-zzz"]);
});