mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-09 14:22:53 +00:00
fix(login-perf): kill relay REQ storms and feedback loops
Real-environment console logs revealed nip-07 login pegging the CPU and starving encrypted-list decryption via relay REQ storms (~1000 REQ/s): - moderationService.rebuildTrustedContacts emitted "contacts" unconditionally, forming an emit->fetch->emit loop (~1600 kind-3 REQ/s). Now emits only on actual change. Regression test added. - Per-video live report (kind 1984) and view-count (kind 30079) subscriptions fan out O(videos x relays) and re-fire on every flaky-relay reconnect. Circuit-broken behind flags until batched (see refactor plan). - onVideosShouldRefresh now coalesces forced reloads (2s leading-edge throttle) so list-change signals can't drive a reload loop. - nip-07 queue reserves one foreground slot; DM decryption demoted to LOW so background DM backfill can't starve feed-driving lists. Test added. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
4bd9503caf
commit
a3b205bfa1
7 files changed
+293
-5
No files matched your search
@@ -0,0 +1,54 @@
|
||||
// Regression test for the nip-07-login CPU-peg / relay REQ storm.
|
||||
//
|
||||
// Scenario (SCN-contacts-emit-on-change):
|
||||
// Given the UI re-fetches trusted contacts whenever the moderation service
|
||||
// emits "contacts" (profileModalController.populateFriendsList ->
|
||||
// ensureViewerContactsLoaded -> fetchTrustedContacts -> rebuildTrustedContacts),
|
||||
// When rebuildTrustedContacts is invoked with an UNCHANGED contact set,
|
||||
// Then "contacts" is NOT emitted — otherwise the emit -> fetch -> emit chain
|
||||
// spins the CPU and floods relays with kind-3 REQs (observed ~1600/s).
|
||||
// And when the set genuinely changes, exactly one "contacts" event fires.
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
withMockedNostrTools,
|
||||
createModerationServiceHarness,
|
||||
} from "../helpers/moderation-test-helpers.mjs";
|
||||
|
||||
const A = "a".repeat(64);
|
||||
const B = "b".repeat(64);
|
||||
|
||||
test("rebuildTrustedContacts emits 'contacts' only when the set changes", (t) => {
|
||||
withMockedNostrTools(t);
|
||||
const { service, capture } = createModerationServiceHarness(t);
|
||||
const emits = capture("contacts");
|
||||
|
||||
// Establish a baseline population (a real change from the initial state).
|
||||
service.rebuildTrustedContacts(new Set([A, B]));
|
||||
const afterFirst = emits.length;
|
||||
assert.ok(afterFirst >= 1, "first real population should emit at least once");
|
||||
|
||||
// Re-applying the SAME set repeatedly must NOT emit. This is the exact loop
|
||||
// that pegged the CPU: identical empty/unchanged rebuilds re-emitting forever.
|
||||
service.rebuildTrustedContacts(new Set([A, B]));
|
||||
service.rebuildTrustedContacts(new Set([A, B]));
|
||||
service.rebuildTrustedContacts(new Set([A, B]));
|
||||
assert.equal(
|
||||
emits.length,
|
||||
afterFirst,
|
||||
"unchanged contact sets must not emit (loop guard)",
|
||||
);
|
||||
|
||||
// A genuine change emits exactly once more.
|
||||
service.rebuildTrustedContacts(new Set([A]));
|
||||
assert.equal(emits.length, afterFirst + 1, "a changed set emits once");
|
||||
|
||||
// ...and re-applying that changed set is again silent.
|
||||
service.rebuildTrustedContacts(new Set([A]));
|
||||
assert.equal(
|
||||
emits.length,
|
||||
afterFirst + 1,
|
||||
"repeating the changed set must not emit",
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user