Purge stale-window entries from the presigned-URL cache
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 29
- Forks
- 14
- Avg merge
- 9d 1h
- Merged PRs (30d)
- 5
Description
Context
S3Bucket._url_cache (added in #661 ) exists so that re-presigning the same object returns the same URL string for a while. boto3 stamps the signing clock into every signature, so without it each poll produced a different URL and the browser re-downloaded frames it already had. The cache key is (bucket_key, url_expiration, window_slot) — see src/app/services/storage.py:155.
Problem
The window slot is part of the key, so when the window rolls over (1h at the default S3_URL_EXPIRATION=24h), every entry from the previous slot becomes permanently unreachable — a lookup can never match an old slot again. Nothing removes them. They only leave through the size-based LRU eviction at src/app/services/storage.py:161-165.
Consequence: an active organization climbs to the 8192-entry ceiling and stays there permanently, with a substantial share of it dead weight from expired windows. Effective capacity is roughly half the nominal figure.
Why this is safe to fix
Worth distinguishing from the existing comment at src/app/services/storage.py:162-164, which argues against clearing the cache. That argument is correct for a full clear() — it would re-presign every URL currently in flight, changing them exactly when stability matters most.
It does not apply to purging stale slots. Those entries are already unreachable by construction, so removing them changes nothing observable: no URL being handed out is affected, and no client sees a different string.
Proposal
A two-generation cache: keep a current dict and a previous dict, swap on slot rollover and drop the old one. O(1), no scan, no per-entry timestamp bookkeeping. The window_slot component of the key becomes redundant and can go.
Impact
Roughly doubles usable capacity for the same memory. No behavioral change for clients. Non-urgent — nothing breaks today, the cache is bounded and a miss only costs a local HMAC signature (generate_presigned_url makes no S3 call).
Related: #671 , which covers the size of the bound itself.
Happy to discuss it :)
Co authored with Claude
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at S3Bucket._url_cache in src/app/services/storage.py around lines 155 and 161-165, then trace how the window slot forms cache keys. Verify the rollover behavior and preserve stable URLs within the active window. Done means stale-slot entries are dropped without scanning, the redundant key component is removed, and current URLs remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100