67f374c470
Avoid re-triggering a USER_BLOCKED account by capping Qobuz to a human-looking volume and cadence. A per-album gate (worker/lyra_worker/qobuz_gate.py) allows Qobuz only within active hours, under today's cap (a warm-up ramp of a steady cap), and past a randomized spacing since the last Qobuz download; the gap spreads the day's budget across active hours with jitter. When the gate is closed the pipeline drops Qobuz candidates so the job falls through to another source (and monitored albums upgrade to Qobuz later); a Qobuz-only setup is never gated. Config keys read live each loop; counters reset at the day boundary via the DB clock. Tunable in Settings -> Qobuz -> Pacing (new /api/qobuz/pacing route). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
38 lines
1.6 KiB
TypeScript
38 lines
1.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { GET, PATCH } from "./route";
|
|
import { prisma } from "@/lib/db";
|
|
|
|
function patch(body: Record<string, string>) {
|
|
return new Request("http://localhost/api/qobuz/pacing", {
|
|
method: "PATCH",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
});
|
|
}
|
|
|
|
describe("qobuz pacing config API", () => {
|
|
it("returns defaults when nothing is stored", async () => {
|
|
const cfg = await (await GET()).json();
|
|
expect(cfg["qobuz.pacing.enabled"]).toBe("true");
|
|
expect(cfg["qobuz.pacing.activeStartHour"]).toBe("8");
|
|
expect(cfg["qobuz.pacing.activeEndHour"]).toBe("23");
|
|
expect(cfg["qobuz.pacing.dailyCap"]).toBe("40");
|
|
expect(cfg["qobuz.pacing.warmupStartDate"]).toBe("");
|
|
});
|
|
|
|
it("round-trips allow-listed settings and persists them", async () => {
|
|
await PATCH(patch({ "qobuz.pacing.dailyCap": "25", "qobuz.pacing.activeStartHour": "9" }));
|
|
const stored = await prisma.config.findUnique({ where: { key: "qobuz.pacing.dailyCap" } });
|
|
expect(stored?.value).toBe("25");
|
|
const cfg = await (await GET()).json();
|
|
expect(cfg["qobuz.pacing.dailyCap"]).toBe("25");
|
|
expect(cfg["qobuz.pacing.activeStartHour"]).toBe("9");
|
|
});
|
|
|
|
it("ignores keys not in the allow-list (e.g. worker-managed counters)", async () => {
|
|
await PATCH(patch({ "qobuz.pacing.countToday": "999", "qobuz.pacing.dailyCap": "30" }));
|
|
expect(await prisma.config.findUnique({ where: { key: "qobuz.pacing.countToday" } })).toBeNull();
|
|
expect((await prisma.config.findUnique({ where: { key: "qobuz.pacing.dailyCap" } }))?.value).toBe("30");
|
|
});
|
|
});
|