Skip to content

Data Models

Engram uses SQLModel for database models, combining SQLAlchemy's ORM with Pydantic's validation.

DiscJob

The central model tracking a disc ripping job through its lifecycle.

app.models.disc_job.DiscJob

Bases: SQLModel

Represents a disc ripping job with full state tracking.

Key Fields

Field Type Description
id int Primary key
drive_id str Drive letter or device path (e.g., E:, /dev/sr0)
volume_label str Disc volume label (e.g., THE_OFFICE_S1)
content_type ContentType tv, movie, or unknown
state JobState Current state in the lifecycle
detected_title str Classified title (e.g., "The Office")
detected_season int Season number for TV shows
classification_source str heuristic, tmdb, or discdb_*
classification_confidence float 0.0 to 1.0
content_hash str TheDiscDB MD5 fingerprint
discdb_mappings_json str Persisted DiscDB title-to-episode mappings
error_message str Error reason if job failed
created_at datetime When the job was created
completed_at datetime When the job reached a terminal state
cleared_at datetime Soft-delete timestamp (hidden from dashboard, still in history)

DiscTitle

Individual title (track) on a disc, linked to a job.

app.models.disc_job.DiscTitle

Bases: SQLModel

Individual title (track) on a disc.

Key Fields

Field Type Description
id int Primary key
job_id int Foreign key to DiscJob
title_index int MakeMKV title index
duration_seconds int Track duration
file_size_bytes int File size
state TitleState Current title state
matched_episode str Matched episode code (e.g., S01E01)
match_confidence float Match confidence score
video_resolution str e.g., 4K, 1080p, 480p
edition str e.g., Extended, Director's Cut
organized_to str Final library path after organization
is_extra bool Whether organized as extra content

Enums

JobState

app.models.disc_job.JobState

Bases: StrEnum

States in the disc processing lifecycle.

Source code in backend/app/models/disc_job.py
class JobState(StrEnum):
    """States in the disc processing lifecycle."""

    IDLE = "idle"
    IDENTIFYING = "identifying"  # Scanning disc structure
    REVIEW_NEEDED = "review_needed"  # Human-in-the-Loop trigger
    RIPPING = "ripping"  # Active extraction
    MATCHING = "matching"  # Audio fingerprinting
    ORGANIZING = "organizing"  # Moving files to library
    COMPLETED = "completed"
    FAILED = "failed"

COMPLETED = 'completed' class-attribute instance-attribute

FAILED = 'failed' class-attribute instance-attribute

IDENTIFYING = 'identifying' class-attribute instance-attribute

IDLE = 'idle' class-attribute instance-attribute

MATCHING = 'matching' class-attribute instance-attribute

ORGANIZING = 'organizing' class-attribute instance-attribute

REVIEW_NEEDED = 'review_needed' class-attribute instance-attribute

RIPPING = 'ripping' class-attribute instance-attribute

ContentType

app.models.disc_job.ContentType

Bases: StrEnum

Type of content on the disc.

Source code in backend/app/models/disc_job.py
class ContentType(StrEnum):
    """Type of content on the disc."""

    TV = "tv"
    MOVIE = "movie"
    UNKNOWN = "unknown"

MOVIE = 'movie' class-attribute instance-attribute

TV = 'tv' class-attribute instance-attribute

UNKNOWN = 'unknown' class-attribute instance-attribute

TitleState

app.models.disc_job.TitleState

Bases: StrEnum

State of an individual title.

Source code in backend/app/models/disc_job.py
class TitleState(StrEnum):
    """State of an individual title."""

    PENDING = "pending"
    RIPPING = "ripping"
    QUEUED = "queued"  # Ripped/on disk, waiting for a matching slot (subtitle + semaphore wait)
    MATCHING = "matching"
    MATCHED = "matched"  # Intermediate state: matched but not yet organized
    REVIEW = "review"  # Ripped successfully but needs human review for episode assignment
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"  # User skipped this track before ripping; excluded, not a failure

COMPLETED = 'completed' class-attribute instance-attribute

FAILED = 'failed' class-attribute instance-attribute

MATCHED = 'matched' class-attribute instance-attribute

MATCHING = 'matching' class-attribute instance-attribute

PENDING = 'pending' class-attribute instance-attribute

QUEUED = 'queued' class-attribute instance-attribute

REVIEW = 'review' class-attribute instance-attribute

RIPPING = 'ripping' class-attribute instance-attribute

SKIPPED = 'skipped' class-attribute instance-attribute

AppConfig

Persisted application configuration, stored in the app_config table.

app.models.AppConfig

Bases: SQLModel

User-configurable application settings stored in database.

Covers paths, API keys, matching parameters, ripping coordination, staging cleanup, extras policy, naming conventions, and drive behavior (auto-eject).

Configuration includes paths (staging, library, MakeMKV, FFmpeg), API keys (TMDB, MakeMKV license), matching parameters, ripping coordination settings, staging cleanup policy, extras policy, and naming conventions.