Skip to content

fix: spend FL tokens even when .torrent is cached (v0.28.1) - #47

Merged
beveradb merged 1 commit into
mainfrom
feat/sess-20260830-2015-fl-token-cache-fix
Aug 30, 2026
Merged

fix: spend FL tokens even when .torrent is cached (v0.28.1)#47
beveradb merged 1 commit into
mainfrom
feat/sess-20260830-2015-fl-token-cache-fix

Conversation

@beveradb

Copy link
Copy Markdown
Collaborator

Problem

After enabling RED_USE_FL_TOKEN on prod, zero freeleech tokens were being spent despite karaoke-gen downloads. Investigation of the flacup logs showed every RED/OPS download hits /download-by-idfetch_artifact_by_id, which served the .torrent from local cache and returned before ever calling the RED download endpoint where usetoken=1 lives (5/5 downloads were cache hits, 0 token attempts).

The v0.28.0 logic assumed ".torrent cached ⇒ already have it ⇒ no token needed." That's wrong: a token is registered server-side via action=download&id=X&usetoken=1, and the .flacfetch cache holds only the tiny .torrent file (2.2 MB total on the box) — the audio data is re-downloaded fresh every time and counts against ratio.

Fix

  • Register the token before the cache short-circuit. Eligible downloads now spend a token even when the .torrent is cached; the cached .torrent is still reused for the actual data fetch.
  • 7-day token ledger prevents re-spending on a torrent that's already personal-freeleech (matches RED's freeleech window):
    • On-disk <id>.tokened markers (survive restarts) + in-memory fallback for when the cache dir is missing/unwritable (per CodeRabbit — avoids a double-spend race with no cache dir).
    • Per-provider lock so concurrent album-batch downloads of the same torrent can't each spend one.
  • Pace spends ≥1s apart (RED rejects faster token spends); pacing trails only successful spends, so an exhausted-token steady state adds no per-download delay.
  • Graceful fallback unchanged: a failed spend falls back to the cached/normal download.

Tests

  • 6 new tests (spend-despite-cache regression, ledger no-respend + TTL, failed-spend fallback, in-memory ledger without cache dir).
  • Full suite: 657 passing.

Review

Local CodeRabbit: 1 major finding (double-spend when cache dir unavailable) → fixed with the in-memory ledger → re-review clean.


@coderabbitai ignore

v0.28.0 only sent usetoken=1 on a .torrent cache MISS, but the local .torrent
cache is unrelated to freeleech: a token is registered server-side via
action=download&id=X&usetoken=1, while the audio DATA is re-downloaded fresh
each time (the cache holds only the tiny .torrent file). Every karaoke-gen
download hits /download-by-id with a cached .torrent, so zero tokens were spent.

- Register the token BEFORE the cache short-circuit; reuse the cached .torrent
  for the actual data fetch.
- Local 7-day token ledger (on-disk <id>.tokened markers + in-memory fallback
  for when the cache dir is unwritable) prevents re-spending within RED's
  personal-freeleech window; a per-provider lock stops concurrent album-batch
  downloads of the same torrent each spending one.
- Pace token spends >=1s apart (RED rejects faster); pacing trails only
  successful spends so an exhausted-token steady state adds no delay.
- 6 new tests; full suite green (657).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.55224% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
flacfetch/providers/gazelle.py 89.55% 7 Missing ⚠️
Flag Coverage Δ
unittests 46.89% <89.55%> (-3.81%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
flacfetch/providers/gazelle.py 79.19% <89.55%> (ø)

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@beveradb
beveradb merged commit 0146638 into main Aug 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant