fix: review round 2 — Clear watch progress clears only the resume point, big view focus by the way it arrived, dialog name, reason tooltip, backfill locks

This commit is contained in:
2026-11-01 18:26:33 +01:00
parent b3402d158f
commit 8dd2f0c015
37 changed files with 457 additions and 243 deletions
+56 -19
View File
@@ -6,9 +6,7 @@ no post text to fall back on, and the download name copied the placeholder too.
the same reel (yt-dlp 2026.08.19, as on prod) still carries the post's text in its description.
"""
import threading
from sqlalchemy import update
from sqlalchemy import select, update
from app.config import settings
from app.db import SessionLocal
@@ -149,8 +147,8 @@ def test_the_backfill_retitles_a_placeholder_download_and_the_names_that_repeate
def test_a_name_given_while_the_backfill_runs_stays(db, make_user, monkeypatch):
# The owner renames the download between the backfill's retitle and its commit (the poster step
# sits between them): the owner's name wins, it is not overwritten by what was read before it.
# The owner renames the download while the backfill reads the page: the owner's name wins, it is
# not overwritten by what was read before it.
_fake_ydl(monkeypatch, _PUBLIC)
owner = make_user()
asset = MediaAsset(
@@ -178,7 +176,9 @@ def test_a_name_given_while_the_backfill_runs_stays(db, make_user, monkeypatch):
db.add(job)
db.commit()
def rename():
read_page = backfill.public_title_info
def renamed_while_reading(*args):
with SessionLocal() as other:
other.execute(
update(DownloadJob)
@@ -186,27 +186,64 @@ def test_a_name_given_while_the_backfill_runs_stays(db, make_user, monkeypatch):
.values(display_name="Office jokes")
)
other.commit()
return read_page(*args)
def poster_while_renamed(a, root):
# A rename that must wait for the backfill's write waits here, and lands after its commit.
t = threading.Thread(target=rename)
t.start()
t.join(timeout=0.5)
renamers.append(t)
return None
renamers: list[threading.Thread] = []
monkeypatch.setattr(backfill.editmod, "ensure_poster", poster_while_renamed)
monkeypatch.setattr(backfill, "public_title_info", renamed_while_reading)
monkeypatch.setattr(backfill.editmod, "ensure_poster", lambda a, root: None)
assert backfill.run()["retitled"] == 1
for t in renamers:
t.join(timeout=10)
assert not t.is_alive()
db.expire_all()
assert db.get(DownloadJob, job.id).display_name == "Office jokes"
def test_the_poster_step_holds_no_row_lock(db, make_user, monkeypatch):
# It can cut a frame for 30 s. A delete locks the asset and then the job: with the job held here
# and the asset still to write, that is a deadlock, and a rename waits out the whole cut.
_fake_ydl(monkeypatch, _PUBLIC)
owner = make_user()
asset = MediaAsset(
source_kind="url",
source_ref=_URL,
format_sig="fb",
status="ready",
rel_path="facebook/x.mp4",
uploader_url="https://www.facebook.com/1",
title="Facebook",
ref_count=1,
)
db.add(asset)
db.flush()
job = DownloadJob(
user_id=owner.id,
asset_id=asset.id,
source_kind="url",
source_ref=_URL,
status="done",
queue_pos=0,
profile_snapshot={},
display_name="Facebook",
)
db.add(job)
db.commit()
asset_id, job_id = asset.id, job.id
def poster_finds_rows_free(a, root):
with SessionLocal() as other:
other.execute(
select(MediaAsset).where(MediaAsset.id == asset_id).with_for_update(nowait=True)
)
other.execute(
select(DownloadJob).where(DownloadJob.id == job_id).with_for_update(nowait=True)
)
other.rollback()
return None
monkeypatch.setattr(backfill.editmod, "ensure_poster", poster_finds_rows_free)
assert backfill.run()["retitled"] == 1
def test_a_download_titled_facebook_is_named_from_the_signed_out_page(
db, make_user, monkeypatch, tmp_path
):