import { redisTest } from "@internal/testcontainers"; import { MollifierBuffer } from "@trigger.dev/redis-worker"; import { describe, expect, vi } from "vitest"; import { createRealTripEvaluator } from "~/v3/mollifier/mollifierTripEvaluator.server"; vi.setConfig({ testTimeout: 30_000 }); // Use a real MollifierBuffer backed by a Redis testcontainer — repo policy // is no mocks for Redis. Per-test envIds keep keys disjoint without explicit // cleanup. We close() the buffer in a finally to release the client. const inputs = { envId: "env_a", orgId: "org_1", taskId: "t1" } as const; describe("createRealTripEvaluator", () => { redisTest( "returns divert=false when the sliding window stays under threshold", async ({ redisOptions }) => { const buffer = new MollifierBuffer({ redisOptions }); try { const evaluator = createRealTripEvaluator({ getBuffer: () => buffer, options: () => ({ windowMs: 1000, threshold: 100, holdMs: 500 }), }); const decision = await evaluator({ ...inputs, envId: "env_under" }); expect(decision).toEqual({ divert: false }); } finally { await buffer.close(); } } ); redisTest( "returns divert=true with reason per_env_rate once the window trips", async ({ redisOptions }) => { const buffer = new MollifierBuffer({ redisOptions }); try { // threshold=2 → the 3rd call within windowMs is the first that trips. const options = { windowMs: 5000, threshold: 2, holdMs: 5000 } as const; const evaluator = createRealTripEvaluator({ getBuffer: () => buffer, options: () => options, }); const envId = "env_trip"; await evaluator({ ...inputs, envId }); await evaluator({ ...inputs, envId }); const decision = await evaluator({ ...inputs, envId }); expect(decision.divert).toBe(true); if (decision.divert) { expect(decision.reason).toBe("per_env_rate"); expect(decision.threshold).toBe(options.threshold); expect(decision.windowMs).toBe(options.windowMs); expect(decision.holdMs).toBe(options.holdMs); expect(decision.count).toBeGreaterThan(options.threshold); } } finally { await buffer.close(); } } ); redisTest("returns divert=false when getBuffer returns null (fail-open)", async () => { const evaluator = createRealTripEvaluator({ getBuffer: () => null, options: () => ({ windowMs: 200, threshold: 100, holdMs: 500 }), }); const decision = await evaluator(inputs); expect(decision).toEqual({ divert: false }); }); redisTest("returns divert=false when buffer throws (fail-open)", async ({ redisOptions }) => { const buffer = new MollifierBuffer({ redisOptions }); // Closing the client up front means evaluateTrip will throw on the first // Redis command — a real failure mode, not a stub. await buffer.close(); const evaluator = createRealTripEvaluator({ getBuffer: () => buffer, options: () => ({ windowMs: 200, threshold: 100, holdMs: 500 }), }); const decision = await evaluator(inputs); expect(decision).toEqual({ divert: false }); }); });