fix(playlists): "+N without length" counts every video the sum left out

The label said "without length" but the count held only live videos, so
a video not fetched yet, or gone before it was, was left out of the sum
and named nowhere. The server's `Video.without_length` and the client's
`isWithoutLength` are now one rule (no length, whatever the live
status), and the field, the key and the helpers are named for what they
count. The comments that still quoted "+N live" say the current copy.
This commit is contained in:
2026-11-08 00:49:21 +01:00
parent 55cbbfb6e4
commit e8b9bdd7c1
17 changed files with 97 additions and 97 deletions
+6 -6
View File
@@ -2,7 +2,7 @@
Measured on prod (2026-11-06): two 24/7 streams' archives report 122,962,914 s and 34,762,459 s, and the
owner's Watch later total read "44,073 hr 55 min". Such a video now has no length on any API answer, the
totals leave it out and count it as `live_without_length`, and the duration filter and sort pass it over
totals leave it out (a playlist's counts it as `without_length`), and the duration filter and sort pass it over
like a video whose length is not fetched yet. An AST check holds who may still read the raw column.
DB lane (the AST check needs none).
"""
@@ -30,7 +30,7 @@ def _seed(db, user):
("day", LENGTH_MAX_S, "was_live"), # exactly a day still is a length
("archive", YEARS, "was_live"),
("onair", None, "live"),
("unfetched", None, "none"), # not live: not counted as "+N live"
("unfetched", None, "none"), # not live, but left out of the sum: counted all the same
]
for i, (vid, seconds, live) in enumerate(rows):
db.add(
@@ -121,7 +121,7 @@ def test_an_off_catalog_archive_has_no_length_either(db, make_user, as_user, mon
assert client.get("/api/videos/offshort").json()["duration_seconds"] == HOUR
def test_the_totals_leave_it_out_and_count_the_live_ones(db, make_user, as_user):
def test_the_totals_leave_it_out_and_count_what_they_left_out(db, make_user, as_user):
user = make_user()
pl = _seed(db, user)
client = as_user(user)
@@ -130,19 +130,19 @@ def test_the_totals_leave_it_out_and_count_the_live_ones(db, make_user, as_user)
assert listed.status_code == 200
(summary,) = [p for p in listed.json() if p["id"] == pl.id]
assert summary["total_duration_seconds"] == KNOWN_SUM
assert summary["live_without_length"] == 2 # the archive and the one on air
assert summary["without_length"] == 3 # the archive, the one on air, the unfetched one
renamed = client.patch(f"/api/playlists/{pl.id}", json={"name": "Later 2"})
assert renamed.status_code == 200
assert renamed.json()["total_duration_seconds"] == KNOWN_SUM
assert renamed.json()["live_without_length"] == 2
assert renamed.json()["without_length"] == 3
channels = client.get("/api/channels")
assert channels.status_code == 200
(ch,) = channels.json()
assert ch["total_duration_seconds"] == KNOWN_SUM
# The channel table shows the sum alone (the count did not fit its column), so it is not sent.
assert "live_without_length" not in ch
assert "without_length" not in ch and "live_without_length" not in ch
def test_the_duration_filter_and_sort_pass_it_over(db, make_user, as_user):