Updated updated path for the new table layout, moved models to a new module

This commit is contained in:
florian committed 2026-11-04 11:17:16 +01:00
1 parent 5296be3a80
commit 79e8de124a
3 files changed
+88 -48

No files matched your search

+52 -47
View File
@@ -5,7 +5,6 @@ from datetime import UTC, datetime
import uvicorn
from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request
from pydantic import BaseModel, Field, computed_field
from seadex import EntryNotFoundError, SeaDexEntry
from service_auth import UserId
@@ -19,30 +18,13 @@ from db_module import (
)
from metrics_server import REQUEST_COUNTER, metrics_api
from secret_manager import cleanup_secret_files
from send_notifications import NotificationClient
from send_notifications import NotificationClient, NotificationUnavailableError, NotificationError
from simple_logger_handler import LOG_LEVEL, setup_logger
from models import AnimeCreate,AnimeEntry,AnimeList
logger = setup_logger(__name__)
class AnimeCreate(BaseModel):
anilist_id: int = Field(gt=0)
class AnimeEntry(BaseModel):
name: str
last_updated: str | None = None
class Counts(BaseModel):
active: int
inactive: int
class AnimeList(BaseModel):
active: list[AnimeEntry] = Field(default_factory=list)
inactive: list[AnimeEntry] = Field(default_factory=list)
@computed_field
@property
def counts(self) -> Counts:
return Counts(active=len(self.active),inactive=len(self.inactive))
@asynccontextmanager
async def lifespan(app: FastAPI):
@@ -113,52 +95,75 @@ def check_seadex(request:Request, db=Depends(get_db)):
with db.cursor() as cursor:
cursor.execute(
"SELECT id, anilist_id, anime_name, last_updated, user_id "
"SELECT id, anilist_id, anime_name, last_updated "
"FROM seadex_state WHERE active = 1"
)
anime = cursor.fetchall()
cache: dict[int, str | None] = {}
logger.debug(f"[FastAPI] Found {len(anime)} active anime to check.")
if not anime[0]:
logger.info("[FastAPI] No active Seadex entries")
return results
with SeaDexEntry() as seadex:
for row_id, anilist_id, anime_name, last_updated, user_id in anime:
for seadex_state_id, anilist_id, anime_name, last_updated in anime:
results["checked"] += 1
try:
if anilist_id not in cache:
cache[anilist_id] = check_for_update(seadex, anilist_id)
current = cache[anilist_id]
current = check_for_update(seadex, anilist_id)
if current is None:
logger.debug(f"[FastAPI] No entry yet for {anime_name} on SeaDex")
logger.debug(f"[FastAPI] No entry yet for Anime: {anime_name} on SeaDex")
continue
if current == last_updated:
continue
if current != last_updated:
logger.info(
f"[FastAPI] {anime_name} updated, Anilist ID: {anilist_id}, User ID: {user_id}"
)
request.app.state.notifier.send(
title=anime_name,
body="SeaDex entry updated",
link=f"https://seadex.moe/{anilist_id}/",
user_id=user_id,
logger.info(f"[FastAPI] Anime: {anime_name} updated, Anilist ID: {anilist_id}")
with db.cursor() as cursor:
cursor.execute(
"SELECT user_id, anime_name as custom_name "
"FROM seadex_state_subscriptions "
"WHERE seadex_state_id = %s AND active = 1",
(seadex_state_id,),
)
subscribers = cursor.fetchall()
with db.cursor() as cursor:
cursor.execute(
"UPDATE seadex_state SET last_updated = %s WHERE id = %s AND user_id = %s",
(current, row_id, user_id),
sent = 0
failed = 0
for user_id, custom_name in subscribers:
try:
request.app.state.notifier.send(
title=custom_name or anime_name,
body="SeaDex entry updated",
link=f"https://seadex.moe/{anilist_id}/",
user_id=user_id,
)
db.commit()
sent += 1
except NotificationUnavailableError:
failed = len(subscribers) - sent
logger.error (f"[FastAPI] Notifications backend unavailable, skipping "
f"{failed} remaining user(s) for Anime: {anime_name}")
break
except NotificationError as e:
failed += 1
logger.error(f"[FastAPI] Failed to send notification to user_id={user_id} for Anime: {anime_name} "
f"status={getattr(e, 'status_code',None)}")
if subscribers and sent == 0:
results["errors"] += 1
logger.error(f"[FastAPI] All notifications failed for Anime: {anime_name}, will retry later")
continue
logger.debug(
f"[FastAPI] Notified and updated db for id={row_id}, "
f"Anilist ID={anilist_id}, User ID: {user_id}"
with db.cursor() as cursor:
cursor.execute(
"UPDATE seadex_state SET last_updated = %s WHERE id = %s",
(current, seadex_state_id),
)
results["new"] += 1
db.commit()
logger.debug(f"[FastAPI] Notification sent and database updated for Anime: {anime_name}")
results["new"] += 1
except Exception:
db.rollback()
results["errors"] += 1
logger.exception(f"[FastAPI] Failed for id={row_id} Anilist={anilist_id}, User ID: {user_id}",)
logger.exception(f"[FastAPI] Failed for id: {seadex_state_id} Anilist: {anilist_id}",)
if results["errors"]:
logger.warning(f"[FastAPI] SeaDex check finished with errors: {results}")
+21
View File
@@ -0,0 +1,21 @@
from pydantic import BaseModel, Field, computed_field
class AnimeCreate(BaseModel):
anilist_id: int = Field(gt=0)
class AnimeEntry(BaseModel):
name: str
last_updated: str | None = None
class Counts(BaseModel):
active: int
inactive: int
class AnimeList(BaseModel):
active: list[AnimeEntry] = Field(default_factory=list)
inactive: list[AnimeEntry] = Field(default_factory=list)
@computed_field
@property
def counts(self) -> Counts:
return Counts(active=len(self.active),inactive=len(self.inactive))