merge: immediate recent backfill on full-history opt-in

This commit is contained in:
npeter83 2026-06-12 00:00:50 +02:00
commit 70d4a9eb69
2 changed files with 22 additions and 2 deletions

View file

@ -8,6 +8,7 @@ from sqlalchemy.orm import Session
from app.auth import current_user, has_write_scope from app.auth import current_user, has_write_scope
from app.db import get_db from app.db import get_db
from app.models import Channel, ChannelTag, Subscription, Tag, User, Video from app.models import Channel, ChannelTag, Subscription, Tag, User, Video
from app.sync.runner import run_recent_backfill
from app.youtube.client import YouTubeClient, YouTubeError from app.youtube.client import YouTubeClient, YouTubeError
router = APIRouter(prefix="/api/channels", tags=["channels"]) router = APIRouter(prefix="/api/channels", tags=["channels"])
@ -84,6 +85,8 @@ def update_channel(
db: Session = Depends(get_db), db: Session = Depends(get_db),
) -> dict: ) -> dict:
sub = _user_subscription(db, user, channel_id) sub = _user_subscription(db, user, channel_id)
channel = db.get(Channel, channel_id)
deep_turned_on = False
if "priority" in payload: if "priority" in payload:
sub.priority = int(payload["priority"]) sub.priority = int(payload["priority"])
if "hidden" in payload: if "hidden" in payload:
@ -92,13 +95,23 @@ def update_channel(
# Opt this channel into (or out of) full-history backfill. The deep scheduler # Opt this channel into (or out of) full-history backfill. The deep scheduler
# picks the flag up on its next run; turning it off won't undo already-fetched # picks the flag up on its next run; turning it off won't undo already-fetched
# videos, it just stops further deep paging if nobody else still wants it. # videos, it just stops further deep paging if nobody else still wants it.
sub.deep_requested = bool(payload["deep_requested"]) want = bool(payload["deep_requested"])
deep_turned_on = want and not sub.deep_requested
sub.deep_requested = want
db.commit() db.commit()
# Opting a channel into full history should give an immediate feed: if we haven't even
# fetched its recent uploads yet, do that one channel now (cheap) instead of waiting for
# the scheduler. Deep paging still follows on the scheduler's next run (recent-then-deep).
if deep_turned_on and channel is not None and channel.recent_synced_at is None:
run_recent_backfill(db, [channel], max_channels=1)
return { return {
"id": channel_id, "id": channel_id,
"priority": sub.priority, "priority": sub.priority,
"hidden": sub.hidden, "hidden": sub.hidden,
"deep_requested": sub.deep_requested, "deep_requested": sub.deep_requested,
"recent_synced": channel.recent_synced_at is not None if channel else None,
} }

View file

@ -44,7 +44,14 @@ export default function Channels({
id: string; id: string;
body: { priority?: number; hidden?: boolean; deep_requested?: boolean }; body: { priority?: number; hidden?: boolean; deep_requested?: boolean };
}) => api.updateChannel(v.id, v.body), }) => api.updateChannel(v.id, v.body),
onSuccess: () => qc.invalidateQueries({ queryKey: ["channels"] }), // Requesting full history may have just pulled in a channel's recent uploads, so
// refresh the per-user status and feed too — not only the channel list.
onSuccess: () => {
qc.invalidateQueries({ queryKey: ["channels"] });
qc.invalidateQueries({ queryKey: ["my-status"] });
qc.invalidateQueries({ queryKey: ["feed"] });
qc.invalidateQueries({ queryKey: ["feed-count"] });
},
}); });
const attach = useMutation({ const attach = useMutation({
mutationFn: (v: { id: string; tagId: number }) => api.attachChannelTag(v.id, v.tagId), mutationFn: (v: { id: string; tagId: number }) => api.attachChannelTag(v.id, v.tagId),