mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-12-06 06:36:25 +00:00
Add status api to get scanner's status
This commit is contained in:
@@ -38,7 +38,7 @@ PUBLIC_URL=http://localhost:8901
|
|||||||
# Set `verified` to true if you don't wanna manually verify users.
|
# Set `verified` to true if you don't wanna manually verify users.
|
||||||
EXTRA_CLAIMS='{"permissions": ["core.read", "core.play"], "verified": false}'
|
EXTRA_CLAIMS='{"permissions": ["core.read", "core.play"], "verified": false}'
|
||||||
# This is the permissions of the first user (aka the first user is admin)
|
# This is the permissions of the first user (aka the first user is admin)
|
||||||
FIRST_USER_CLAIMS='{"permissions": ["users.read", "users.write", "apikeys.read", "apikeys.write", "users.delete", "core.read", "core.write", "core.play", "scanner.trigger"], "verified": true}'
|
FIRST_USER_CLAIMS='{"permissions": ["users.read", "users.write", "users.delete", "apikeys.read", "apikeys.write", "core.read", "core.write", "core.play", "scanner.trigger"], "verified": true}'
|
||||||
|
|
||||||
# Guest (meaning unlogged in users) can be:
|
# Guest (meaning unlogged in users) can be:
|
||||||
# unauthorized (they need to connect before doing anything)
|
# unauthorized (they need to connect before doing anything)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from datetime import datetime
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
@@ -18,3 +19,15 @@ class Request(Model, extra="allow"):
|
|||||||
class Video(Model):
|
class Video(Model):
|
||||||
id: str
|
id: str
|
||||||
episodes: list[Guess.Episode]
|
episodes: list[Guess.Episode]
|
||||||
|
|
||||||
|
class RequestRet(Model):
|
||||||
|
id: str
|
||||||
|
kind: Literal["episode", "movie"]
|
||||||
|
title: str
|
||||||
|
year: int | None
|
||||||
|
status: Literal[
|
||||||
|
"pending",
|
||||||
|
"running",
|
||||||
|
"failed",
|
||||||
|
]
|
||||||
|
started_at: datetime | None
|
||||||
|
|||||||
16
scanner/scanner/routers/health.py
Normal file
16
scanner/scanner/routers/health.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from fastapi import APIRouter
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/health")
|
||||||
|
def get_health():
|
||||||
|
return {"status": "healthy"}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/ready")
|
||||||
|
def get_ready():
|
||||||
|
# child spans (`select 1` & db connection reset) was still logged,
|
||||||
|
# since i don't really wanna deal with it, let's just do that.
|
||||||
|
return {"status": "healthy"}
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated, Literal
|
||||||
|
|
||||||
from asyncpg import Connection
|
from fastapi import APIRouter, BackgroundTasks, Depends, Security
|
||||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Security
|
|
||||||
|
|
||||||
from scanner.database import get_db_fapi
|
from scanner.models.request import RequestRet
|
||||||
|
from scanner.status import StatusService
|
||||||
|
|
||||||
from ..fsscan import create_scanner
|
from ..fsscan import create_scanner
|
||||||
from ..jwt import validate_bearer
|
from ..jwt import validate_bearer
|
||||||
@@ -11,6 +11,19 @@ from ..jwt import validate_bearer
|
|||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/scan")
|
||||||
|
async def get_scan_status(
|
||||||
|
svc: Annotated[StatusService, Depends(StatusService.create)],
|
||||||
|
_: Annotated[None, Security(validate_bearer, scopes=["scanner.trigger"])],
|
||||||
|
status: Literal["pending", "running", "failed"] | None = None,
|
||||||
|
) -> list[RequestRet]:
|
||||||
|
"""
|
||||||
|
Get scan status, know what tasks are running, pending or failed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return await svc.list_requests(status=status)
|
||||||
|
|
||||||
|
|
||||||
@router.put(
|
@router.put(
|
||||||
"/scan",
|
"/scan",
|
||||||
status_code=204,
|
status_code=204,
|
||||||
@@ -29,25 +42,3 @@ async def trigger_scan(
|
|||||||
await scanner.scan()
|
await scanner.scan()
|
||||||
|
|
||||||
tasks.add_task(run)
|
tasks.add_task(run)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/health")
|
|
||||||
def get_health():
|
|
||||||
return {"status": "healthy"}
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/ready")
|
|
||||||
def get_ready():
|
|
||||||
# child spans (`select 1` & db connection reset) was still logged,
|
|
||||||
# since i don't really wanna deal with it, let's just do that.
|
|
||||||
return {"status": "healthy"}
|
|
||||||
|
|
||||||
|
|
||||||
# async def get_ready(db: Annotated[Connection, Depends(get_db_fapi)]):
|
|
||||||
# try:
|
|
||||||
# _ = await db.execute("select 1")
|
|
||||||
# return {"status": "healthy", "database": "healthy"}
|
|
||||||
# except Exception as e:
|
|
||||||
# raise HTTPException(
|
|
||||||
# status_code=500, detail={"status": "unhealthy", "database": str(e)}
|
|
||||||
# )
|
|
||||||
|
|||||||
41
scanner/scanner/status.py
Normal file
41
scanner/scanner/status.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
from asyncpg import Connection
|
||||||
|
from pydantic import TypeAdapter
|
||||||
|
|
||||||
|
from scanner.database import get_db
|
||||||
|
|
||||||
|
from .models.request import RequestRet
|
||||||
|
|
||||||
|
|
||||||
|
class StatusService:
|
||||||
|
def __init__(self, database: Connection):
|
||||||
|
self._database = database
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def create(cls):
|
||||||
|
async with get_db() as db:
|
||||||
|
yield StatusService(db)
|
||||||
|
|
||||||
|
async def list_requests(
|
||||||
|
self, *, status: Literal["pending", "running", "failed"] | None = None
|
||||||
|
) -> list[RequestRet]:
|
||||||
|
ret = await self._database.fetch(
|
||||||
|
f"""
|
||||||
|
select
|
||||||
|
pk::text as id,
|
||||||
|
kind,
|
||||||
|
title,
|
||||||
|
year,
|
||||||
|
status,
|
||||||
|
started_at
|
||||||
|
from
|
||||||
|
scanner.requests
|
||||||
|
order by
|
||||||
|
started_at,
|
||||||
|
pk
|
||||||
|
{"where status = $1" if status is not None else ""}
|
||||||
|
""",
|
||||||
|
*([status] if status is not None else []),
|
||||||
|
)
|
||||||
|
return TypeAdapter(list[RequestRet]).validate_python(ret)
|
||||||
Reference in New Issue
Block a user