feat(channels): admin reset / re-backfill endpoint
POST /api/channels/{id}/reset-backfill (admin-only): clear the channel's backfill
markers, re-opt into deep backfill and re-run its recent pull now — a re-fetch-from-
scratch trigger regardless of current sync state. Idempotent (videos upsert by id).
This commit is contained in:
parent
9872a0115c
commit
0210b84166
2 changed files with 27 additions and 0 deletions
|
|
@ -9,6 +9,7 @@ from app import quota
|
||||||
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.routes.admin import admin_user
|
||||||
from app.sync.runner import run_recent_backfill
|
from app.sync.runner import run_recent_backfill
|
||||||
from app.youtube.client import YouTubeClient, YouTubeError
|
from app.youtube.client import YouTubeClient, YouTubeError
|
||||||
|
|
||||||
|
|
@ -134,6 +135,30 @@ def update_channel(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{channel_id}/reset-backfill")
|
||||||
|
def reset_backfill(
|
||||||
|
channel_id: str,
|
||||||
|
user: User = Depends(admin_user),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
) -> dict:
|
||||||
|
"""Admin-only reset: re-fetch this channel from scratch regardless of its current sync
|
||||||
|
state (a "reset" trigger). Clears the channel's backfill markers, opts it back into deep
|
||||||
|
backfill, and re-runs its recent pull immediately; the deep scheduler re-pages the full
|
||||||
|
back-catalog on its next run. Idempotent — videos upsert by id, so nothing duplicates."""
|
||||||
|
channel = db.get(Channel, channel_id)
|
||||||
|
if channel is None:
|
||||||
|
raise HTTPException(status_code=404, detail="Unknown channel")
|
||||||
|
sub = _user_subscription(db, user, channel_id)
|
||||||
|
channel.backfill_done = False
|
||||||
|
channel.backfill_cursor = None
|
||||||
|
channel.recent_synced_at = None
|
||||||
|
sub.deep_requested = True
|
||||||
|
db.commit()
|
||||||
|
with quota.attribute(user.id, "backfill_recent"):
|
||||||
|
run_recent_backfill(db, [channel], max_channels=1)
|
||||||
|
return {"id": channel_id, "reset": True}
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{channel_id}/subscription")
|
@router.delete("/{channel_id}/subscription")
|
||||||
def unsubscribe(
|
def unsubscribe(
|
||||||
channel_id: str,
|
channel_id: str,
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,8 @@ export const api = {
|
||||||
id: string,
|
id: string,
|
||||||
patch: { priority?: number; hidden?: boolean; deep_requested?: boolean }
|
patch: { priority?: number; hidden?: boolean; deep_requested?: boolean }
|
||||||
) => req(`/api/channels/${id}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
) => req(`/api/channels/${id}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
||||||
|
resetChannelBackfill: (id: string) =>
|
||||||
|
req(`/api/channels/${id}/reset-backfill`, { method: "POST" }),
|
||||||
deepAll: (on = true) =>
|
deepAll: (on = true) =>
|
||||||
req(`/api/sync/deep-all?on=${on}`, { method: "POST" }),
|
req(`/api/sync/deep-all?on=${on}`, { method: "POST" }),
|
||||||
attachChannelTag: (id: string, tagId: number) =>
|
attachChannelTag: (id: string, tagId: number) =>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue