add route to check state of latest IMDb movie import

This commit is contained in:
ducklet 2021-07-22 00:05:02 +02:00
parent 1fd592cb1d
commit fe5db535a9
4 changed files with 87 additions and 26 deletions

View file

@ -9,6 +9,7 @@ from databases import Database
from . import config from . import config
from .models import ( from .models import (
Movie, Movie,
Progress,
Rating, Rating,
User, User,
asplain, asplain,
@ -125,34 +126,32 @@ async def apply_db_patches(db: Database):
await db.execute("vacuum") await db.execute("vacuum")
async def get_import_progress() -> float: async def get_import_progress() -> Optional[Progress]:
"""Return the current import progress percentage. """Return the latest import progress."""
return await get(Progress, type="import-imdb-movies", order_by="started DESC")
The progress will be a value from 0 to 100. If the value is 100, the last
import was completed successfully and no import is currently running.
"""
query = "SELECT state FROM progress WHERE id='import_imdb'"
state = await shared_connection().fetch_val(query)
return float(state or 100)
async def set_import_progress(progress: float): async def set_import_progress(progress: float) -> Progress:
"""Set the current import progress percentage.""" """Set the current import progress percentage."""
progress = min(max(0.0, progress), 100.0) # clamp to 0 <= progress <= 100 progress = min(max(0.0, progress), 100.0) # clamp to 0 <= progress <= 100
values = {"id": "import_imdb"} current = await get_import_progress()
is_update = current and current.stopped is None
if not current or not is_update:
current = Progress(type="import-imdb-movies")
current.state = f"{progress:.2f}"
if progress >= 100: if progress >= 100:
query = "DELETE FROM progress WHERE id=:id" current.stopped = utcnow().isoformat()
else:
query = """
INSERT INTO progress(id, state, started)
VALUES (:id, :state, :started)
ON CONFLICT DO UPDATE SET state=excluded.state
"""
values.update({"state": f"{progress:.2f}", "started": utcnow().isoformat()})
await shared_connection().execute(query=query, values=values) if is_update:
await update(current)
else:
await add(current)
return current
def shared_connection() -> Database: def shared_connection() -> Database:
@ -183,7 +182,9 @@ async def add(item):
ModelType = TypeVar("ModelType") ModelType = TypeVar("ModelType")
async def get(model: Type[ModelType], **kwds) -> Optional[ModelType]: async def get(
model: Type[ModelType], *, order_by: str = None, **kwds
) -> Optional[ModelType]:
values = {k: v for k, v in kwds.items() if v is not None} values = {k: v for k, v in kwds.items() if v is not None}
if not values: if not values:
return return
@ -191,6 +192,8 @@ async def get(model: Type[ModelType], **kwds) -> Optional[ModelType]:
fields_ = ", ".join(f.name for f in fields(model)) fields_ = ", ".join(f.name for f in fields(model))
cond = " AND ".join(f"{k}=:{k}" for k in values) cond = " AND ".join(f"{k}=:{k}" for k in values)
query = f"SELECT {fields_} FROM {model._table} WHERE {cond}" query = f"SELECT {fields_} FROM {model._table} WHERE {cond}"
if order_by:
query += f" ORDER BY {order_by}"
row = await shared_connection().fetch_one(query=query, values=values) row = await shared_connection().fetch_one(query=query, values=values)
return fromplain(model, row) if row else None return fromplain(model, row) if row else None

View file

@ -140,6 +140,17 @@ def utcnow():
return datetime.now().replace(tzinfo=timezone.utc) return datetime.now().replace(tzinfo=timezone.utc)
@dataclass
class Progress:
_table: ClassVar[str] = "progress"
id: ULID = field(default_factory=ULID)
type: str = None
state: str = None
started: datetime = field(default_factory=utcnow)
stopped: Optional[str] = None
@dataclass @dataclass
class Movie: class Movie:
_table: ClassVar[str] = "movies" _table: ClassVar[str] = "movies"

View file

@ -0,0 +1,24 @@
-- add IMDb vote count
CREATE TABLE _migrate_progress (
id TEXT PRIMARY KEY NOT NULL,
type TEXT NOT NULL,
state TEXT NOT NULL,
started TEXT NOT NULL,
stopped TEXT
);;
INSERT INTO _migrate_progress
SELECT
id,
'import-imdb-movies' AS type,
state,
started,
NULL AS stopped
FROM progress
WHERE true;;
DROP TABLE progress;;
ALTER TABLE _migrate_progress
RENAME TO progress;;

View file

@ -23,7 +23,7 @@ from starlette.routing import Mount, Route
from . import config, db, imdb, imdb_import from . import config, db, imdb, imdb_import
from .db import close_connection_pool, find_ratings, open_connection_pool from .db import close_connection_pool, find_ratings, open_connection_pool
from .middleware.responsetime import ResponseTimeMiddleware from .middleware.responsetime import ResponseTimeMiddleware
from .models import Group, Movie, User, asplain from .models import Group, Movie, Progress, User, asplain
from .types import ULID from .types import ULID
from .utils import b64encode, phc_compare, phc_scrypt from .utils import b64encode, phc_compare, phc_scrypt
@ -198,14 +198,37 @@ async def add_movie(request):
import_lock = asyncio.Lock() import_lock = asyncio.Lock()
@route("/movies/_reload_imdb", methods=["GET"])
@requires(["authenticated", "admin"])
async def progress_for_load_imdb_movies(request):
progress = await db.get_import_progress()
if not progress:
return JSONResponse({"status": "No import exists."}, status_code=404)
p = asplain(progress)
percent = float(p["state"])
return JSONResponse(
{
"status": "Import is running." if percent < 100 else "Import finished.",
"progress": percent,
"started": p["started"],
"stopped": p["stopped"],
}
)
@route("/movies/_reload_imdb", methods=["POST"]) @route("/movies/_reload_imdb", methods=["POST"])
@requires(["authenticated", "admin"]) @requires(["authenticated", "admin"])
async def load_imdb_movies(request): async def load_imdb_movies(request):
async with import_lock: async with import_lock:
progress = await db.get_import_progress() progress = await db.get_import_progress()
if progress < 100: if progress:
percent = float(progress.state)
if percent < 100:
return JSONResponse( return JSONResponse(
{"status": "Import running.", "progress": progress}, status_code=409 {"status": "Import is running.", "progress": percent},
status_code=409,
) )
await db.set_import_progress(0) await db.set_import_progress(0)