Files
NixReaperandClaude Sonnet 5 c20df1c503
CI / lint (push) Canceled after 0s
CI / typecheck (push) Canceled after 0s
CI / unit-tests (push) Canceled after 0s
CI / integration-tests (push) Canceled after 0s
CI / container-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
Initial Aurora Core 0.1 implementation
Production-grade media metadata backend per docs/aurora-core-spec.md:
Aurora-owned UUIDv7 identity system, normalized movie/TV/people/credits
schema, provider abstraction with a TMDb adapter, an idempotent async
ingestion pipeline (normalize -> match -> upsert -> provenance), a
Postgres FTS/trigram search layer, a stateless FastAPI v1 API with
Redis caching/rate-limiting, arq workers, dev/prod Docker Compose
topologies, unit + integration + load tests, CI, and architecture/
database/API/ERD documentation.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-04 17:34:03 -05:00

81 lines
2.4 KiB
Python

"""Declarative base and shared mixins for all Aurora Core models."""
from __future__ import annotations
import uuid
from datetime import datetime
from sqlalchemy import DateTime, Enum, MetaData, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from uuid6 import uuid7
from app.models.enums import (
ArtworkType,
CompanyType,
IngestionJobStatus,
MatchConfidence,
MovieStatus,
SeriesStatus,
VideoType,
)
NAMING_CONVENTION = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
def _enum_column(enum_cls: type) -> Enum:
"""Store our str-Enum members by `.value` (lowercase snake_case), not
`.name`, which is what SQLAlchemy's Enum type does by default. Without
this, the DB would store e.g. "RELEASED" while every part of the
codebase (schemas, ingestion, API filters) works with "released"."""
return Enum(
enum_cls,
values_callable=lambda obj: [e.value for e in obj],
name=f"{enum_cls.__name__.lower()}_enum",
)
class Base(DeclarativeBase):
"""Base class for all ORM models. Naming convention keeps Alembic's
autogenerated constraint names stable across databases."""
metadata = MetaData(naming_convention=NAMING_CONVENTION)
type_annotation_map = {
MovieStatus: _enum_column(MovieStatus),
SeriesStatus: _enum_column(SeriesStatus),
ArtworkType: _enum_column(ArtworkType),
VideoType: _enum_column(VideoType),
CompanyType: _enum_column(CompanyType),
IngestionJobStatus: _enum_column(IngestionJobStatus),
MatchConfidence: _enum_column(MatchConfidence),
}
class UUIDPrimaryKeyMixin:
"""UUIDv7 primary key. Time-ordered so it stays btree-friendly and can
double as a creation-order cursor, unlike a random UUIDv4."""
id: Mapped[uuid.UUID] = mapped_column(
primary_key=True,
default=lambda: uuid.UUID(str(uuid7())),
)
class TimestampMixin:
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)