"""The Qobuz budget gate, wired into the pipeline: when the gate is closed the job falls through to another source; when open it uses Qobuz and records the download; a Qobuz-only setup is never gated (nothing to fall through to).""" from lyra_worker.adapters.fakes import FakeQobuz, FakeSoulseek from lyra_worker.claim import claim_next from lyra_worker.pipeline import run_pipeline from tests.conftest import insert_request def _cfg(conn, key, value): with conn.cursor() as cur: cur.execute( 'INSERT INTO "Config"(key,value,secret,"updatedAt") VALUES (%s,%s,false,now()) ' 'ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value, "updatedAt"=now()', (key, value), ) conn.commit() def _open_gate(conn): _cfg(conn, "qobuz.pacing.activeStartHour", "0") _cfg(conn, "qobuz.pacing.activeEndHour", "24") def _closed_gate(conn): _cfg(conn, "qobuz.pacing.activeStartHour", "5") # empty window (5..5) → always closed _cfg(conn, "qobuz.pacing.activeEndHour", "5") def _state(conn, job_id): with conn.cursor() as cur: cur.execute('SELECT state FROM "Job" WHERE id = %s', (job_id,)) return cur.fetchone()[0] def _chosen(conn, job_id): with conn.cursor() as cur: cur.execute('SELECT source FROM "Candidate" WHERE "jobId" = %s AND chosen = true', (job_id,)) row = cur.fetchone() return row[0] if row else None def _cfg_get(conn, key): with conn.cursor() as cur: cur.execute('SELECT value FROM "Config" WHERE key = %s', (key,)) row = cur.fetchone() return row[0] if row else None def test_closed_gate_drops_qobuz_and_falls_through(conn): _closed_gate(conn) job_id = insert_request(conn, artist="Radiohead", album="In Rainbows") claim_next(conn) run_pipeline(conn, job_id, [FakeQobuz(), FakeSoulseek()], dest_root="/tmp/lib-gate") assert _state(conn, job_id) == "imported" assert _chosen(conn, job_id) == "soulseek" # Qobuz dropped by the closed gate def test_open_gate_uses_qobuz_and_records_the_download(conn): _open_gate(conn) job_id = insert_request(conn, artist="Radiohead", album="In Rainbows") claim_next(conn) run_pipeline(conn, job_id, [FakeQobuz(), FakeSoulseek()], dest_root="/tmp/lib-gate") assert _state(conn, job_id) == "imported" assert _chosen(conn, job_id) == "qobuz" assert _cfg_get(conn, "qobuz.pacing.countToday") == "1" # recorded against today's budget assert _cfg_get(conn, "qobuz.pacing.nextAllowedAt") is not None def test_qobuz_only_setup_is_never_gated(conn): _closed_gate(conn) job_id = insert_request(conn, artist="Radiohead", album="In Rainbows") claim_next(conn) run_pipeline(conn, job_id, [FakeQobuz()], dest_root="/tmp/lib-gate") assert _state(conn, job_id) == "imported" assert _chosen(conn, job_id) == "qobuz" # not dropped — nothing to fall through to def test_non_qobuz_download_does_not_touch_the_counter(conn): _closed_gate(conn) # forces Soulseek job_id = insert_request(conn, artist="Radiohead", album="In Rainbows") claim_next(conn) run_pipeline(conn, job_id, [FakeQobuz(), FakeSoulseek()], dest_root="/tmp/lib-gate") assert _chosen(conn, job_id) == "soulseek" assert _cfg_get(conn, "qobuz.pacing.countToday") is None # only Qobuz downloads count