refactor(sync): the empty-answer rule for a mirror is one function, vanished()

The YouTube playlist guard from the previous commit put sync/playlists.py over its size ceiling;
the rule now lives beside should_prune as vanished(existing, listed), which the mirror calls in
place of its own list. The pyright baseline also drops by one (187), from the plex/overlay split.
This commit is contained in:
2026-10-03 19:45:14 +02:00
parent 4fc307c426
commit c4abbe48c1
3 changed files with 14 additions and 21 deletions
-8
View File
@@ -580,14 +580,6 @@
"endColumn": 89, "endColumn": 89,
"lineCount": 1 "lineCount": 1
} }
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 17,
"endColumn": 18,
"lineCount": 1
}
} }
], ],
"./app/plex/tmdb.py": [ "./app/plex/tmdb.py": [
+4 -12
View File
@@ -22,7 +22,7 @@ from app import logs, progress, quota
from app.auth import has_read_scope from app.auth import has_read_scope
from app.models import Channel, Playlist, PlaylistItem, User, Video from app.models import Channel, Playlist, PlaylistItem, User, Video
from app.sync.runner import token_users from app.sync.runner import token_users
from app.sync.subscriptions import should_prune from app.sync.subscriptions import vanished
from app.sync.videos import apply_video_details, parse_dt from app.sync.videos import apply_video_details, parse_dt
from app.youtube.client import YouTubeClient, YouTubeError from app.youtube.client import YouTubeClient, YouTubeError
@@ -338,18 +338,10 @@ def pull_user_playlists(db: Session, user: User) -> dict:
Playlist.source == "local", Playlist.source == "local",
Playlist.yt_playlist_id.is_not(None), Playlist.yt_playlist_id.is_not(None),
) )
) ).scalars()
.scalars()
.all()
)
# Drop mirrors whose YouTube playlist no longer exists — locked first, as every item write.
# Never on an empty answer that contradicts the mirrors we hold: the same 200-with-no-items
# blip `should_prune` guards the subscriptions against would drop every mirror (E32 S2).
gone = (
[pl for ytid, pl in existing.items() if ytid not in yt_ids]
if should_prune(len(yt_ids), len(existing))
else []
) )
# Drop vanished mirrors (none on an empty answer) — locked first, as every item write.
gone = vanished(existing, yt_ids)
if gone: if gone:
lock_playlists(db, *(pl.id for pl in gone)) lock_playlists(db, *(pl.id for pl in gone))
for pl in gone: for pl in gone:
+10 -1
View File
@@ -1,6 +1,6 @@
"""Import the authenticated user's YouTube subscriptions and channel metadata.""" """Import the authenticated user's YouTube subscriptions and channel metadata."""
from collections.abc import Iterable from collections.abc import Collection, Iterable
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from sqlalchemy import or_, select from sqlalchemy import or_, select
@@ -119,6 +119,15 @@ def should_prune(fetched_count: int, existing_count: int) -> bool:
return fetched_count > 0 or existing_count == 0 return fetched_count > 0 or existing_count == 0
def vanished[K, V](existing: dict[K, V], listed: Collection[K]) -> list[V]:
"""The local mirrors whose key the remote listing no longer has — none at all when the listing
is an empty answer that contradicts them (`should_prune`). The YouTube playlist mirrors use it:
without it, one blip dropped every mirror (E32 S2)."""
if not should_prune(len(listed), len(existing)):
return []
return [row for key, row in existing.items() if key not in listed]
def import_subscriptions(db: Session, user: User) -> dict: def import_subscriptions(db: Session, user: User) -> dict:
"""Pull all subscriptions for `user`, upsert channels + subscription links, prune """Pull all subscriptions for `user`, upsert channels + subscription links, prune
channels the user has unsubscribed from on YouTube, and fetch channel details for channels the user has unsubscribed from on YouTube, and fetch channel details for