refactor(catalog): the HTTP layer reads through queries and writes through the service
Channels, search and sync do no database work in their routes any more: reads go through catalog/queries, writes through catalog/service, and a live search's ingest is catalog/search. What a catalog route needs from Reader (a playlist's channels, a user's tag links, the feed projection of results) it asks reader/queries and reader/service. The scheduler and the runs page read channel titles and the work queue through catalog/queries. Catalog is fenced below its HTTP layer: its owner filters go through userscope, it reads no other unit's tables, and its ingest jobs commit only where they are named.
This commit is contained in:
@@ -16,7 +16,7 @@ from datetime import datetime, timezone
|
||||
from app import sysconfig
|
||||
from app.models import User
|
||||
from app.catalog.models import Video
|
||||
from app.routes.search import _ingest_candidates
|
||||
from app.catalog.search import ingest_candidates
|
||||
|
||||
|
||||
class _FakeYT:
|
||||
@@ -71,7 +71,7 @@ def test_scrape_ingest_dateless_stub_ingests_and_takes_real_enrich_date(db):
|
||||
"vid_bbbbbbb": _enrich_item("vid_bbbbbbb", "2023-10-30T17:00:08Z"),
|
||||
}
|
||||
|
||||
kept = _ingest_candidates(db, _FakeYT(enrich), user, candidates)
|
||||
kept = ingest_candidates(db, _FakeYT(enrich), user, candidates)
|
||||
|
||||
# No IntegrityError, and both non-Short/non-live videos are kept in input order.
|
||||
assert kept == ["vid_aaaaaaa", "vid_bbbbbbb"]
|
||||
@@ -89,7 +89,7 @@ def test_scrape_ingest_enrich_miss_keeps_nonnull_placeholder(db):
|
||||
db.add(user)
|
||||
db.commit()
|
||||
|
||||
kept = _ingest_candidates(db, _FakeYT({}), user, [_candidate("vid_ccccccc", "UC_chan_c")])
|
||||
kept = ingest_candidates(db, _FakeYT({}), user, [_candidate("vid_ccccccc", "UC_chan_c")])
|
||||
|
||||
assert kept == []
|
||||
c = db.get(Video, "vid_ccccccc")
|
||||
@@ -101,7 +101,7 @@ def test_search_youtube_route_returns_422_when_ingest_fails(db, monkeypatch, ove
|
||||
# Route-level guard (B-core-1): an ingest failure with nothing yet collected must surface as a 422
|
||||
# + message on this JSON endpoint (the FE hides 5xx behind a generic "connection lost" + auto-retry,
|
||||
# burning a second quota-costed search), and the session is rolled back. Here the page fetch succeeds
|
||||
# (one candidate) and _ingest_candidates raises → the endpoint returns 422.
|
||||
# (one candidate) and ingest_candidates raises → the endpoint returns 422.
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.state as state
|
||||
@@ -144,7 +144,7 @@ def test_search_youtube_route_returns_422_when_ingest_fails(db, monkeypatch, ove
|
||||
def _boom(db_, yt, user_, candidates):
|
||||
raise RuntimeError("ingest exploded")
|
||||
|
||||
monkeypatch.setattr(search_mod, "_ingest_candidates", _boom)
|
||||
monkeypatch.setattr(search_mod.catalog_search, "ingest_candidates", _boom)
|
||||
|
||||
override_dep(get_db, db.info["request"])
|
||||
override_dep(current_user, lambda: user)
|
||||
|
||||
Reference in New Issue
Block a user