mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Add agent metric archive diagnostic switch
Add an environment-controlled kill switch that removes kind 44200 from archive relay subscriptions without disturbing observer or other archive kinds. Prevent startup seeding from re-adding the metric kind while the switch is active. Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
This commit is contained in:
@@ -425,6 +425,43 @@ test("manager_builds_correct_filter_for_owner_p", async () => {
|
||||
mgr.destroy();
|
||||
});
|
||||
|
||||
test("manager_metric_kill_switch_filters_only_kind_44200", async () => {
|
||||
const relay = makeFakeRelayClient();
|
||||
const archive = makeFakeArchive();
|
||||
archive.setSubs([
|
||||
{
|
||||
scopeType: "owner_p",
|
||||
scopeValue: "mixed",
|
||||
kinds: [24200, 44200, 9],
|
||||
identityPubkey: "pk",
|
||||
relayUrl: "wss://r",
|
||||
createdAt: 0,
|
||||
},
|
||||
{
|
||||
scopeType: "owner_p",
|
||||
scopeValue: "metric-only",
|
||||
kinds: [44200],
|
||||
identityPubkey: "pk",
|
||||
relayUrl: "wss://r",
|
||||
createdAt: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
const mgr = makeManager(relay, archive, {
|
||||
disableAgentMetricArchive: true,
|
||||
});
|
||||
await mgr.start();
|
||||
await tick();
|
||||
|
||||
const activeFilters = [...relay.subs.values()]
|
||||
.filter((entry) => !entry.unsubbed)
|
||||
.map((entry) => entry.filter);
|
||||
assert.deepEqual(activeFilters, [
|
||||
{ kinds: [24200, 9], limit: 0, "#p": ["mixed"] },
|
||||
]);
|
||||
mgr.destroy();
|
||||
});
|
||||
|
||||
test("manager_forwards_events_to_archive_events_on_flush", async () => {
|
||||
const relay = makeFakeRelayClient();
|
||||
const archive = makeFakeArchive();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { relayClient as defaultRelayClient } from "@/shared/api/relayClient";
|
||||
import type { RelaySubscriptionFilter } from "@/shared/api/relayClientShared";
|
||||
import type { RelayEvent } from "@/shared/api/types";
|
||||
import { KIND_AGENT_TURN_METRIC } from "@/shared/constants/kinds";
|
||||
import {
|
||||
archiveEvents as defaultArchiveEvents,
|
||||
listSaveSubscriptions as defaultListSaveSubscriptions,
|
||||
@@ -15,6 +16,8 @@ import {
|
||||
|
||||
const FLUSH_BATCH_SIZE = 25;
|
||||
const FLUSH_IDLE_MS = 2_000;
|
||||
const DISABLE_AGENT_METRIC_ARCHIVE =
|
||||
import.meta.env?.VITE_BUZZ_DISABLE_AGENT_METRIC_ARCHIVE === "1";
|
||||
|
||||
// ── Types ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -34,6 +37,7 @@ export interface ArchiveSyncDeps {
|
||||
}>,
|
||||
) => Promise<ArchiveBatchResult>;
|
||||
onSubscriptionChange: (listener: () => void) => () => void;
|
||||
disableAgentMetricArchive?: boolean;
|
||||
flushBatchSize?: number;
|
||||
flushIdleMs?: number;
|
||||
}
|
||||
@@ -81,8 +85,12 @@ function scopeKey(scopeType: ScopeType, scopeValue: string): string {
|
||||
*/
|
||||
export class ArchiveSyncManager {
|
||||
private readonly deps: Required<
|
||||
Omit<ArchiveSyncDeps, "flushBatchSize" | "flushIdleMs">
|
||||
Omit<
|
||||
ArchiveSyncDeps,
|
||||
"disableAgentMetricArchive" | "flushBatchSize" | "flushIdleMs"
|
||||
>
|
||||
>;
|
||||
private readonly disableAgentMetricArchive: boolean;
|
||||
private readonly flushBatchSize: number;
|
||||
private readonly flushIdleMs: number;
|
||||
|
||||
@@ -112,6 +120,8 @@ export class ArchiveSyncManager {
|
||||
onSubscriptionChange:
|
||||
deps?.onSubscriptionChange ?? defaultOnSubscriptionChange,
|
||||
};
|
||||
this.disableAgentMetricArchive =
|
||||
deps?.disableAgentMetricArchive ?? DISABLE_AGENT_METRIC_ARCHIVE;
|
||||
this.flushBatchSize = deps?.flushBatchSize ?? FLUSH_BATCH_SIZE;
|
||||
this.flushIdleMs = deps?.flushIdleMs ?? FLUSH_IDLE_MS;
|
||||
}
|
||||
@@ -202,6 +212,15 @@ export class ArchiveSyncManager {
|
||||
|
||||
if (this.destroyed) return;
|
||||
|
||||
if (this.disableAgentMetricArchive) {
|
||||
subs = subs.flatMap((sub) => {
|
||||
const kinds = sub.kinds.filter(
|
||||
(kind) => kind !== KIND_AGENT_TURN_METRIC,
|
||||
);
|
||||
return kinds.length > 0 ? [{ ...sub, kinds }] : [];
|
||||
});
|
||||
}
|
||||
|
||||
// Full keys (scope+kinds) for the current subscription list.
|
||||
const wanted = new Set(
|
||||
subs.map((s) => subKey(s.scopeType, s.scopeValue, s.kinds)),
|
||||
|
||||
@@ -10,11 +10,16 @@ import test from "node:test";
|
||||
|
||||
// ── Fake deps factory ────────────────────────────────────────────────────────
|
||||
|
||||
function makeDeps({ hasExplicitChoice = false, mergeShouldFail = false } = {}) {
|
||||
function makeDeps({
|
||||
hasExplicitChoice = false,
|
||||
mergeShouldFail = false,
|
||||
disableAgentMetricArchive = false,
|
||||
} = {}) {
|
||||
const calls = { mergeSaveSubscriptionKinds: [], setExplicitChoice: [] };
|
||||
|
||||
return {
|
||||
calls,
|
||||
disableAgentMetricArchive,
|
||||
mergeSaveSubscriptionKinds: async (kind) => {
|
||||
if (mergeShouldFail) throw new Error("merge failed");
|
||||
calls.mergeSaveSubscriptionKinds.push({ kind });
|
||||
@@ -31,7 +36,7 @@ function makeDeps({ hasExplicitChoice = false, mergeShouldFail = false } = {}) {
|
||||
const KIND_AGENT_TURN_METRIC = 44200;
|
||||
|
||||
async function runSeed(pubkey, deps) {
|
||||
if (!pubkey) return;
|
||||
if (!pubkey || deps.disableAgentMetricArchive) return;
|
||||
if (deps.hasExplicitChoice(pubkey)) return;
|
||||
|
||||
try {
|
||||
@@ -71,6 +76,14 @@ test("test_default_enabled_persists_explicit_choice_after_seed", async () => {
|
||||
assert.equal(deps.calls.setExplicitChoice[0].enabled, true);
|
||||
});
|
||||
|
||||
test("test_kill_switch_does_not_seed_or_persist_choice", async () => {
|
||||
const deps = makeDeps({ disableAgentMetricArchive: true });
|
||||
await runSeed("pubkey123", deps);
|
||||
|
||||
assert.equal(deps.calls.mergeSaveSubscriptionKinds.length, 0);
|
||||
assert.equal(deps.calls.setExplicitChoice.length, 0);
|
||||
});
|
||||
|
||||
test("test_explicit_choice_set_does_not_reseed", async () => {
|
||||
const deps = makeDeps({ hasExplicitChoice: true });
|
||||
await runSeed("pubkey123", deps);
|
||||
|
||||
@@ -30,12 +30,15 @@ export interface AgentMetricArchiveSeedDeps {
|
||||
mergeSaveSubscriptionKinds: (kind: number) => Promise<void>;
|
||||
hasExplicitChoice: (pubkey: string) => boolean;
|
||||
setExplicitChoice: (pubkey: string, enabled: boolean) => void;
|
||||
disableAgentMetricArchive: boolean;
|
||||
}
|
||||
|
||||
const defaultDeps: AgentMetricArchiveSeedDeps = {
|
||||
mergeSaveSubscriptionKinds,
|
||||
hasExplicitChoice: hasExplicitAgentMetricArchiveChoice,
|
||||
setExplicitChoice: setExplicitAgentMetricArchiveChoice,
|
||||
disableAgentMetricArchive:
|
||||
import.meta.env?.VITE_BUZZ_DISABLE_AGENT_METRIC_ARCHIVE === "1",
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -51,7 +54,7 @@ export function useAgentMetricArchiveSeed(
|
||||
deps: AgentMetricArchiveSeedDeps = defaultDeps,
|
||||
): void {
|
||||
React.useEffect(() => {
|
||||
if (!pubkey) return;
|
||||
if (!pubkey || deps.disableAgentMetricArchive) return;
|
||||
|
||||
// Already made an explicit choice for this identity — never re-seed.
|
||||
if (deps.hasExplicitChoice(pubkey)) return;
|
||||
|
||||
Reference in New Issue
Block a user