diff --git a/backend/alembic/versions/0064_add_updated_at_indexes.py b/backend/alembic/versions/0064_add_updated_at_indexes.py new file mode 100644 index 000000000..999438f80 --- /dev/null +++ b/backend/alembic/versions/0064_add_updated_at_indexes.py @@ -0,0 +1,31 @@ +"""Add indexes on updated_at for roms and platforms tables + +Revision ID: 0064_add_updated_at_indexes +Revises: 0063_roms_metadata_player_count +Create Date: 2026-01-12 + +""" + +from alembic import op + +# revision identifiers, used by Alembic. +revision = "0064_add_updated_at_indexes" +down_revision = "0063_roms_metadata_player_count" +branch_labels = None +depends_on = None + + +def upgrade(): + with op.batch_alter_table("roms", schema=None) as batch_op: + batch_op.create_index("ix_roms_updated_at", ["updated_at"], unique=False) + + with op.batch_alter_table("platforms", schema=None) as batch_op: + batch_op.create_index("ix_platforms_updated_at", ["updated_at"], unique=False) + + +def downgrade(): + with op.batch_alter_table("roms", schema=None) as batch_op: + batch_op.drop_index("ix_roms_updated_at") + + with op.batch_alter_table("platforms", schema=None) as batch_op: + batch_op.drop_index("ix_platforms_updated_at") diff --git a/backend/endpoints/platform.py b/backend/endpoints/platform.py index c8da143ca..9f77f766d 100644 --- a/backend/endpoints/platform.py +++ b/backend/endpoints/platform.py @@ -1,8 +1,9 @@ +from datetime import datetime from typing import Annotated from fastapi import Body from fastapi import Path as PathVar -from fastapi import Request, status +from fastapi import Query, Request, status from decorators.auth import protected_route from endpoints.responses.platform import PlatformSchema @@ -48,11 +49,20 @@ async def add_platform( @protected_route(router.get, "", [Scope.PLATFORMS_READ]) -def get_platforms(request: Request) -> list[PlatformSchema]: +def get_platforms( + request: Request, + updated_after: Annotated[ + datetime | None, + Query( + description="Filter platforms updated after this datetime (ISO 8601 format with timezone information)." + ), + ] = None, +) -> list[PlatformSchema]: """Retrieve platforms.""" return [ - PlatformSchema.model_validate(p) for p in db_platform_handler.get_platforms() + PlatformSchema.model_validate(p) + for p in db_platform_handler.get_platforms(updated_after=updated_after) ] diff --git a/backend/endpoints/rom.py b/backend/endpoints/rom.py index cfffdec02..62cecac97 100644 --- a/backend/endpoints/rom.py +++ b/backend/endpoints/rom.py @@ -405,6 +405,12 @@ def get_roms( str, Query(description="Order direction, either 'asc' or 'desc'."), ] = "asc", + updated_after: Annotated[ + datetime | None, + Query( + description="Filter roms updated after this datetime (ISO 8601 format with timezone information)." + ), + ] = None, ) -> CustomLimitOffsetPage[SimpleRomSchema]: """Retrieve roms.""" query, order_by_attr = db_rom_handler.get_roms_query( @@ -450,6 +456,7 @@ def get_roms( statuses_logic=statuses_logic, player_counts_logic=player_counts_logic, group_by_meta_id=group_by_meta_id, + updated_after=updated_after, ) # Get the char index for the roms diff --git a/backend/handler/database/platforms_handler.py b/backend/handler/database/platforms_handler.py index 16709413c..f53ba7ffd 100644 --- a/backend/handler/database/platforms_handler.py +++ b/backend/handler/database/platforms_handler.py @@ -1,5 +1,6 @@ import functools from collections.abc import Sequence +from datetime import datetime from sqlalchemy import delete, or_, select, update from sqlalchemy.orm import Query, Session, selectinload @@ -65,9 +66,12 @@ class DBPlatformsHandler(DBBaseHandler): @with_firmware def get_platforms( self, + updated_after: datetime | None = None, query: Query = None, # type: ignore session: Session = None, # type: ignore ) -> Sequence[Platform]: + if updated_after: + query = query.filter(Platform.updated_at > updated_after) return session.scalars(query.order_by(Platform.name.asc())).unique().all() @begin_session diff --git a/backend/handler/database/roms_handler.py b/backend/handler/database/roms_handler.py index 1c995616c..5af0593e8 100644 --- a/backend/handler/database/roms_handler.py +++ b/backend/handler/database/roms_handler.py @@ -1,5 +1,6 @@ import functools from collections.abc import Iterable, Sequence +from datetime import datetime from typing import Any from sqlalchemy import ( @@ -510,6 +511,7 @@ class DBRomsHandler(DBBaseHandler): statuses_logic: str = "any", player_counts_logic: str = "any", user_id: int | None = None, + updated_after: datetime | None = None, session: Session = None, # type: ignore ) -> Query[Rom]: from handler.scan_handler import MetadataSource @@ -563,6 +565,9 @@ class DBRomsHandler(DBBaseHandler): if verified: query = self.filter_by_verified(query) + if updated_after: + query = query.filter(Rom.updated_at > updated_after) + # BEWARE YE WHO ENTERS HERE 💀 if group_by_meta_id: # Convert NULL is_main_sibling to 0 (false) so it sorts after true values