refactor: one definition of a followed channel and of a choice spelling

The explore purge rebuilt followed_channel's two EXISTS clauses inline, so what is polled and what may be deleted could drift; it now uses the predicate, which moved to sync/explore.py. The env validator and sysconfig each folded a choice value on their own; both call config.canonical_choice. The deep-backfill comment no longer calls recent backfill unconditional.
This commit is contained in:
2026-09-17 03:53:29 +02:00
parent 86bc008a81
commit 4bfba4aa86
5 changed files with 40 additions and 32 deletions
+5 -17
View File
@@ -10,14 +10,15 @@ import threading
from collections import Counter
from concurrent.futures import ThreadPoolExecutor, as_completed
from sqlalchemy import or_, select
from sqlalchemy import select
from sqlalchemy.orm import Session
from app import logs, progress, quota, sysconfig
log = logging.getLogger("siftlode.sync")
from app.db import SessionLocal
from app.models import Channel, ExploredChannel, OAuthToken, Subscription, User
from app.models import Channel, OAuthToken, Subscription, User
from app.sync.explore import followed_channel
from app.sync.subscriptions import import_subscriptions
from app.sync.videos import (
apply_rss_feed,
@@ -54,20 +55,6 @@ def get_service_user(db: Session) -> User | None:
return users[0] if users else None
def followed_channel():
"""WHERE clause: a channel somebody follows — a subscription, or an exploration still inside its
grace window. The scheduled RSS poll and recent backfill cover only these (owner decision,
2026-09-17). They used to cover EVERY channel row, but rows also come from search results,
playlist sync and dropped subscriptions, and nothing deletes those: on prod 582 of 979 polled
channels had no follower, three of them dead feeds answering 404 on every poll. The cost of
narrowing is deliberate: the shared Library stops receiving new uploads from channels nobody
follows."""
return or_(
select(Subscription.id).where(Subscription.channel_id == Channel.id).exists(),
select(ExploredChannel.id).where(ExploredChannel.channel_id == Channel.id).exists(),
)
def run_rss_poll(db: Session, channels: list[Channel] | None = None) -> dict[str, int]:
"""Poll the free RSS feed of every followed channel (`followed_channel`). Returns `{"new": inserted, "failed": channels_that_did
_not_complete}` — the failure count is part of the RESULT, not just a log line, so the scheduler
@@ -258,7 +245,8 @@ def run_deep_backfill(db: Session, max_channels: int = 10, max_pages: int = 5) -
if user is None:
return {"channels_processed": 0, "videos_added": 0, "reason": "no service user"}
# Demand-driven: only deep-backfill channels at least one user has opted into
# (Subscription.deep_requested). Recent backfill stays unconditional (cheap).
# (Subscription.deep_requested). Recent backfill needs no opt-in: it covers every followed channel
# (`followed_channel`).
deep_requested = (
select(Subscription.id)
.where(