wip: Link videos found after request started

This commit is contained in:
Zoe Roux 2025-05-10 01:14:56 +02:00
parent dda496d88b
commit 479e91e2e2
No known key found for this signature in database
4 changed files with 35 additions and 28 deletions

View File

@ -68,7 +68,7 @@ export const enqueueOptImage = async (
kind: "image", kind: "image",
message, message,
}); });
await tx.execute(sql`notify image`); await tx.execute(sql`notify kyoo.image`);
return { return {
id, id,
@ -128,7 +128,7 @@ export const processImages = async () => {
const client = (await db.$client.connect()) as PoolClient; const client = (await db.$client.connect()) as PoolClient;
client.on("notification", (evt) => { client.on("notification", (evt) => {
if (evt.channel !== "image") return; if (evt.channel !== "kyoo.image") return;
processAll(); processAll();
}); });
await client.query("listen image"); await client.query("listen image");

View File

@ -21,8 +21,7 @@ create table scanner.requests(
status scanner.request_status not null, status scanner.request_status not null,
started_at created_at timestamptz, started_at created_at timestamptz,
created_at created_at timestamptz not null default now() ::timestamptz, created_at created_at timestamptz not null default now() ::timestamptz,
constraint unique_kty(kind, title, year), constraint unique_kty(kind, title, year)
constraint unique_eid(external_id)
); );
commit; commit;

View File

@ -5,7 +5,7 @@ from aiohttp import ClientSession
from .models.movie import Movie from .models.movie import Movie
from .models.serie import Serie from .models.serie import Serie
from .models.videos import Video, VideoCreated, VideoInfo from .models.videos import Resource, Video, VideoCreated, VideoInfo
logger = getLogger(__name__) logger = getLogger(__name__)
@ -50,16 +50,18 @@ class KyooClient:
) as r: ) as r:
r.raise_for_status() r.raise_for_status()
async def create_movie(self, movie: Movie): async def create_movie(self, movie: Movie) -> Resource:
async with self._client.post( async with self._client.post(
"movies", "movies",
json=movie.model_dump_json(), json=movie.model_dump_json(),
) as r: ) as r:
r.raise_for_status() r.raise_for_status()
return Resource(**await r.json())
async def create_serie(self, serie: Serie): async def create_serie(self, serie: Serie) -> Resource:
async with self._client.post( async with self._client.post(
"series", "series",
json=serie.model_dump_json(), json=serie.model_dump_json(),
) as r: ) as r:
r.raise_for_status() r.raise_for_status()
return Resource(**await r.json())

View File

@ -4,11 +4,11 @@ from logging import getLogger
from typing import Literal from typing import Literal
from psycopg import AsyncConnection from psycopg import AsyncConnection
from psycopg.rows import class_row from psycopg.rows import class_row, dict_row
from pydantic import Field from pydantic import Field
from .client import KyooClient from .client import KyooClient
from .models.videos import Guess from .models.videos import Guess, Resource
from .providers.composite import CompositeProvider from .providers.composite import CompositeProvider
from .utils import Model from .utils import Model
@ -16,7 +16,7 @@ logger = getLogger(__name__)
class Request(Model, extra="allow"): class Request(Model, extra="allow"):
pk: int = Field(exclude=True) pk: int | None = Field(exclude=True, default=None)
kind: Literal["episode", "movie"] kind: Literal["episode", "movie"]
title: str title: str
year: int | None year: int | None
@ -51,15 +51,15 @@ class RequestProcessor:
""", """,
(x.model_dump() for x in requests), (x.model_dump() for x in requests),
) )
# TODO: how will this conflict be handled if the request is already locked for update (being processed) # TODO: how will this conflict be handled if the request is already running
if cur.rowcount > 0: if cur.rowcount > 0:
_ = await cur.execute("notify requests") _ = await cur.execute("notify scanner.requests")
async def process_requests(self): async def process_requests(self):
_ = await self._database.execute("listen requests") async with await self._database.execute("listen scanner.requests"):
gen = self._database.notifies() gen = self._database.notifies()
async for _ in gen: async for _ in gen:
await self._process_request() await self._process_request()
async def _process_request(self): async def _process_request(self):
async with self._database.cursor(row_factory=class_row(Request)) as cur: async with self._database.cursor(row_factory=class_row(Request)) as cur:
@ -91,14 +91,21 @@ class RequestProcessor:
logger.info(f"Starting to process {request.title}") logger.info(f"Starting to process {request.title}")
try: try:
await self._run_request(request) show = await self._run_request(request)
cur = await cur.execute(
""" async with self._database.cursor(row_factory=dict_row) as cur:
delete from scanner.requests cur = await cur.execute(
where pk = %s """
""", delete from scanner.requests
[request.pk], where pk = %s
) returning
videos
""",
[request.pk],
)
finished = await anext(cur)
if finished["videos"] != request.videos:
await self._client.link_videos(show.slug, finished["videos"])
except Exception as e: except Exception as e:
logger.error("Couldn't process request", exc_info=e) logger.error("Couldn't process request", exc_info=e)
cur = await cur.execute( cur = await cur.execute(
@ -113,7 +120,7 @@ class RequestProcessor:
[request.pk], [request.pk],
) )
async def _run_request(self, request: Request): async def _run_request(self, request: Request) -> Resource:
if request.kind == "movie": if request.kind == "movie":
movie = await self._providers.find_movie( movie = await self._providers.find_movie(
request.title, request.title,
@ -121,8 +128,7 @@ class RequestProcessor:
request.external_id, request.external_id,
) )
movie.videos = [x.id for x in request.videos] movie.videos = [x.id for x in request.videos]
await self._client.create_movie(movie) return await self._client.create_movie(movie)
return
serie = await self._providers.find_serie( serie = await self._providers.find_serie(
request.title, request.title,
@ -149,4 +155,4 @@ class RequestProcessor:
) )
continue continue
entry.videos.append(vid.id) entry.videos.append(vid.id)
await self._client.create_serie(serie) return await self._client.create_serie(serie)