File size: 3,273 Bytes
1b2323a
 
 
 
 
 
 
 
 
 
 
 
 
 
8bf0d31
1b2323a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1fed801
 
 
1b2323a
 
 
1fed801
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from __future__ import annotations

from datetime import datetime
from uuid import uuid4

from sqlalchemy import (
    CheckConstraint,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    JSON,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column

from app.security.models import Base, utcnow


class ProjectRenderJob(Base):
    """A durable render of one immutable editor revision snapshot."""

    __tablename__ = "project_render_jobs"
    __table_args__ = (
        UniqueConstraint(
            "project_id",
            "editor_revision",
            "idempotency_key",
            name="uq_project_render_idempotency",
        ),
        CheckConstraint(
            "status in ('queued', 'processing', 'completed', 'failed', 'cancelling', 'cancelled')",
            name="ck_project_render_status",
        ),
        Index("ix_project_render_jobs_workspace_status", "workspace_id", "status"),
        Index("ix_project_render_jobs_project_created", "project_id", "created_at"),
        Index("ix_project_render_jobs_dispatch", "status", "next_attempt_at"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="RESTRICT"), nullable=False
    )
    project_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("projects.id", ondelete="RESTRICT"), nullable=False
    )
    editor_revision: Mapped[int] = mapped_column(Integer, nullable=False)
    editor_schema_version: Mapped[int] = mapped_column(Integer, nullable=False)
    editor_state_json: Mapped[dict[str, object]] = mapped_column(
        "editor_state", JSON, nullable=False
    )
    render_settings_json: Mapped[dict[str, object]] = mapped_column(
        "render_settings", JSON, nullable=False
    )
    request_fingerprint: Mapped[str] = mapped_column(String(64), nullable=False)
    idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False)
    requested_by: Mapped[str] = mapped_column(
        String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
    )
    status: Mapped[str] = mapped_column(String(32), nullable=False, default="queued")
    attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    max_attempts: Mapped[int] = mapped_column(Integer, nullable=False, default=3)
    next_attempt_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    output_asset_id: Mapped[str | None] = mapped_column(
        String(36), ForeignKey("media_assets.id", ondelete="RESTRICT")
    )
    error_code: Mapped[str | None] = mapped_column(String(100))
    error_message: Mapped[str | None] = mapped_column(Text)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow
    )
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    cancelled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow, onupdate=utcnow
    )