fix(downloads): a download larger than the space left says so, not "processing failed"
yt-dlp refuses a file announced over `max_filesize` by logging one line and returning with no file (measured, and pinned in test_formats against a local server): the worker found no output and failed the job as `postprocess`. `formats.watching_size_cap` now sees that line through our yt-dlp logger, and the download (and, should it ever happen, a YouTube clip's range fetch) fails as the owner's refusal with DOWNLOAD_TOO_BIG_MESSAGE, classified `quota_exceeded`. The download's quota copy says it does not fit in what is left — true at a full cap too — instead of "Storage full". A pre-existing type error the change touched is fixed (baseline down by one).
This commit is contained in:
@@ -11,7 +11,8 @@ its OWN session, so every test COMMITS its setup before calling it.
|
||||
"""
|
||||
|
||||
from app.config import settings
|
||||
from app.downloads import pipeline, quota
|
||||
from app.downloads import errors as dlerrors
|
||||
from app.downloads import formats, pipeline, quota
|
||||
from app.models import DownloadJob, DownloadQuota, MediaAsset, User
|
||||
from app.worker import _claim_job
|
||||
|
||||
@@ -297,3 +298,49 @@ def test_a_refusal_for_one_user_does_not_poison_the_shared_asset(db, monkeypatch
|
||||
assert db.get(MediaAsset, shared.id).status == "pending"
|
||||
assert db.get(MediaAsset, shared.id).error is None
|
||||
assert db.get(DownloadJob, theirs.id).status == "queued"
|
||||
|
||||
|
||||
def test_a_download_over_the_space_left_says_so_and_releases_the_shared_asset(
|
||||
db, monkeypatch, tmp_path
|
||||
):
|
||||
# yt-dlp refuses a file over `max_filesize` by saying so and returning with no file (pinned in
|
||||
# test_formats). That is the owner's storage, not a processing fault: their refusal, in words
|
||||
# true of a cap with space still left, and the shared asset goes back for the next job.
|
||||
monkeypatch.setattr(settings, "download_root", str(tmp_path))
|
||||
u = User(email="nearcap@example.com")
|
||||
db.add(u)
|
||||
db.flush()
|
||||
db.add(
|
||||
DownloadQuota(user_id=u.id, max_bytes=1000, max_concurrent=2, max_jobs=100, unlimited=False)
|
||||
)
|
||||
held = _sized_asset(db, 400, "near-held")
|
||||
_job(db, u.id, queue_pos=0, status="done", asset_id=held.id)
|
||||
shared = MediaAsset(
|
||||
source_kind="youtube",
|
||||
source_ref="y" * 11,
|
||||
format_sig="s",
|
||||
status="downloading",
|
||||
ref_count=1,
|
||||
)
|
||||
db.add(shared)
|
||||
db.flush()
|
||||
mine = _job(db, u.id, queue_pos=1, status="running", asset_id=shared.id)
|
||||
db.commit()
|
||||
caps = []
|
||||
|
||||
def refuses_over_the_cap(*args, max_bytes=None, **kwargs):
|
||||
caps.append(max_bytes)
|
||||
formats._YDL_LOG.debug(
|
||||
f"[download] File is larger than max-filesize (2000 bytes > {max_bytes} bytes). Aborting."
|
||||
)
|
||||
return {"id": "y" * 11, "requested_downloads": [{}]}
|
||||
|
||||
monkeypatch.setattr(pipeline, "_extract_with_fallback", refuses_over_the_cap)
|
||||
pipeline._download(mine.id, shared.id, "youtube", "y" * 11, {}, u.id)
|
||||
|
||||
db.expire_all()
|
||||
job = db.get(DownloadJob, mine.id)
|
||||
assert caps == [600]
|
||||
assert (job.status, job.error_code) == ("error", "quota_exceeded")
|
||||
assert job.error == dlerrors.DOWNLOAD_TOO_BIG_MESSAGE
|
||||
assert db.get(MediaAsset, shared.id).status == "pending"
|
||||
|
||||
Reference in New Issue
Block a user