From 92c9ee42dcd3041bd53cb14fb3928922914e1719 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:57:28 -0700 Subject: [PATCH] Test that eviction stops at the low-water mark --- src/workerd.bounds.test.ts | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/workerd.bounds.test.ts b/src/workerd.bounds.test.ts index c810161..7e6b4aa 100644 --- a/src/workerd.bounds.test.ts +++ b/src/workerd.bounds.test.ts @@ -36,7 +36,10 @@ const bounds = { } as const /** Start the built worker; given the directory of a stopped collector, on that collector's store. */ -const startCollector = async (settings: Partial> = {}, reuse?: string) => { +const startCollector = async ( + settings: Partial> = {}, + reuse?: string, +) => { const directory = reuse ?? (await mkdtemp(path.join(tmpdir(), "motel-bounds-"))) const port = await freePort() const inspector = await freePort() @@ -258,6 +261,38 @@ test("workerd collector keeps its database file within the size bound between re await rm(collector.directory, { recursive: true, force: true }) }, 120_000) +test("workerd collector evicts down to its low-water mark instead of once per export", async () => { + // Only the ingest path holds the bound here. Evicting back to exactly the bound leaves the + // store full, so every later export crossed it again and paid for another eviction pass. + const collector = await startCollector({ + MOTEL_OTEL_MAX_SPANS: 10_000_000, + MOTEL_OTEL_MAX_DB_SIZE_MB: 4, + MOTEL_OTEL_EVICTION_LOW_WATER_PERCENT: 50, + MOTEL_OTEL_RETENTION_INTERVAL_SECONDS: 3_600, + }) + const exports = 120 + let evictions: { passes: number; traces: number } + try { + for (let tick = 0; tick < exports; tick++) { + const response = await post(collector.origin, JSON.stringify(traceExport(100))) + expect(response.status).toBe(200) + await response.arrayBuffer() + } + const status = (await (await fetch(`${collector.origin}/api/ingest`)).json()) as { evictions: typeof evictions } + evictions = status.evictions + } finally { + await collector.stop() + } + const stored = await storedTelemetry(collector.directory) + expect(stored.bytes).toBeLessThanOrEqual(4 * mebibyte) + // About 30 MiB arrive, a quarter MiB per export. Once full, each pass frees 2 MiB, room for + // about eight exports, so passes number about a ninth of the exports. One per export after + // the store first filled would be over a hundred. + expect(evictions.passes).toBeGreaterThan(0) + expect(evictions.passes).toBeLessThanOrEqual(exports / 4) + await rm(collector.directory, { recursive: true, force: true }) +}, 120_000) + test("workerd collector refuses ingest beyond its queue and size bounds and counts what it refused", async () => { const collector = await startCollector() const held: Array> = []