41 lines
1.8 KiB
Python
41 lines
1.8 KiB
Python
"""Managed thumbnail cache records.
|
|
|
|
One row per ``cache_key`` (pixel hash + size + algorithm version, or the source
|
|
byte hash for undecodable inputs). The row records whether generation succeeded or
|
|
failed and why, so a broken original is not retried on every request. Because the
|
|
key contains the normalized pixel hash, an EXIF-only change reuses the thumbnail
|
|
and a genuine pixel change invalidates it automatically.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from photo_pipeline.db import Base
|
|
|
|
|
|
class Thumbnail(Base):
|
|
__tablename__ = "thumbnails"
|
|
|
|
cache_key: Mapped[str] = mapped_column(String, primary_key=True)
|
|
asset_id: Mapped[str] = mapped_column(ForeignKey("assets.id"), nullable=False)
|
|
size: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
state: Mapped[str] = mapped_column(String, nullable=False) # ready | error
|
|
error_code: Mapped[str | None] = mapped_column(String)
|
|
path: Mapped[str | None] = mapped_column(String)
|
|
width: Mapped[int | None] = mapped_column(Integer)
|
|
height: Mapped[int | None] = mapped_column(Integer)
|
|
format: Mapped[str | None] = mapped_column(String)
|
|
# Durable comparison evidence for an archived asset: never evicted by the LRU
|
|
# quota, because the original may be on a medium that is no longer reachable.
|
|
protected: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, server_default=func.now()
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now()
|
|
)
|