Initial Aurora Core 0.1 implementation
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
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
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]>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""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,
|
||||
)
|
||||
Reference in New Issue
Block a user