refactor: R12 S3 — invert scheduler->routes, publish cross-module privates
Layering cleanup, no behaviour change (ruff clean backend+scripts, pytest 193): - Invert the scheduler->routes dependency: reset_demo_state (+ its demo-seed helpers) move from routes/admin.py to a new service module app/demo.py. Both routes/admin.py and scheduler.py now import it from app.demo, so the scheduler no longer reaches into the routes layer — its lazy import (the routes<->scheduler cycle workaround) is gone, hoisted to a top-level import. - Publish the private symbols that were imported across module boundaries (the underscore convention was lying): feed._serialize -> serialize, feed._to_tsquery_str -> to_tsquery_str, videos._insert_stubs -> insert_stubs, videos._stub_from_playlist_item -> stub_from_playlist_item, worker._uploader_url -> uploader_url, plex._shared._item_or_404 -> item_or_404. Scoped renames — the 5 other route modules keep their own truly private _serialize helpers. - _release_asset moves from routes/downloads.py to app/downloads/service.py as the public release_asset (asset bookkeeping is a service concern); the routes call it via service.release_asset.
This commit is contained in:
@@ -44,7 +44,7 @@ def parse_dt(value: str | None) -> datetime | None:
|
||||
return None
|
||||
|
||||
|
||||
def _insert_stubs(db: Session, rows: list[dict]) -> int:
|
||||
def insert_stubs(db: Session, rows: list[dict]) -> int:
|
||||
"""Idempotently insert video stubs; returns the number of newly inserted rows.
|
||||
|
||||
Uses RETURNING so the count is exact (ON CONFLICT DO NOTHING leaves rowcount
|
||||
@@ -76,7 +76,7 @@ def apply_rss_feed(db: Session, channel: Channel, entries: list[dict]) -> int:
|
||||
"""Insert new video stubs from an already-fetched feed and stamp the channel's last RSS
|
||||
time. DB-only — must run on the session's own thread; the network fetch
|
||||
(fetch_channel_feed) is kept separate so callers like run_rss_poll can parallelise it."""
|
||||
inserted = _insert_stubs(db, entries)
|
||||
inserted = insert_stubs(db, entries)
|
||||
channel.last_rss_at = _now()
|
||||
db.add(channel)
|
||||
db.commit()
|
||||
@@ -84,7 +84,7 @@ def apply_rss_feed(db: Session, channel: Channel, entries: list[dict]) -> int:
|
||||
|
||||
|
||||
# --- Backfill (uploads playlist; costs quota) ---
|
||||
def _stub_from_playlist_item(item: dict, channel_id: str) -> dict | None:
|
||||
def stub_from_playlist_item(item: dict, channel_id: str) -> dict | None:
|
||||
content = item.get("contentDetails", {})
|
||||
snippet = item.get("snippet", {})
|
||||
video_id = content.get("videoId")
|
||||
@@ -120,7 +120,7 @@ def backfill_channel_recent(db: Session, yt: YouTubeClient, channel: Channel) ->
|
||||
data = yt.get_playlist_items(channel.uploads_playlist_id, page_token)
|
||||
stopped_mid_page = False
|
||||
for item in data.get("items", []):
|
||||
stub = _stub_from_playlist_item(item, channel.id)
|
||||
stub = stub_from_playlist_item(item, channel.id)
|
||||
if stub is None:
|
||||
continue
|
||||
if stub["published_at"] and stub["published_at"] < cutoff:
|
||||
@@ -147,7 +147,7 @@ def backfill_channel_recent(db: Session, yt: YouTubeClient, channel: Channel) ->
|
||||
channel.recent_synced_at = _now()
|
||||
channel.backfill_cursor = next_cursor
|
||||
channel.backfill_done = done
|
||||
inserted = _insert_stubs(db, collected)
|
||||
inserted = insert_stubs(db, collected)
|
||||
db.add(channel)
|
||||
db.commit()
|
||||
return inserted
|
||||
@@ -166,11 +166,11 @@ def backfill_channel_deep(
|
||||
rows = [
|
||||
s
|
||||
for s in (
|
||||
_stub_from_playlist_item(it, channel.id) for it in data.get("items", [])
|
||||
stub_from_playlist_item(it, channel.id) for it in data.get("items", [])
|
||||
)
|
||||
if s is not None
|
||||
]
|
||||
total += _insert_stubs(db, rows)
|
||||
total += insert_stubs(db, rows)
|
||||
page_token = data.get("nextPageToken")
|
||||
channel.backfill_cursor = page_token
|
||||
if not page_token:
|
||||
|
||||
Reference in New Issue
Block a user