Files
HartOMat/backend/alembic/versions/040_media_assets.py
T
Hartmut 7706c514c8 fix(deploy): fix render-worker build context + migration 040 idempotency
- docker-compose.yml: change render-worker build context from ./render-worker
  to . (project root) so pyproject.toml is accessible; update dockerfile path
- render-worker/Dockerfile: update COPY paths for new build context;
  install Python 3.11 via deadsnakes PPA (Ubuntu 22.04 ships 3.10 which
  fails the >=3.11 requirement in pyproject.toml)
- 040_media_assets.py: rewrite upgrade() with raw idempotent SQL (CREATE TYPE
  inside DO $$ EXCEPTION WHEN duplicate_object $$; CREATE TABLE IF NOT EXISTS;
  CREATE INDEX IF NOT EXISTS) to handle pre-existing enum from partial runs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 17:32:42 +01:00

74 lines
2.6 KiB
Python

"""Add media_assets table.
Revision ID: 040
Revises: 039
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects.postgresql import UUID, JSONB
revision = '040'
down_revision = '039'
branch_labels = None
depends_on = None
def upgrade():
# Use raw SQL throughout for full idempotency (enum may exist from a partial run)
op.execute("""
DO $$ BEGIN
CREATE TYPE media_asset_type AS ENUM (
'thumbnail','still','turntable','stl_low','stl_high',
'gltf_geometry','gltf_production','blend_production'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
""")
op.execute("""
CREATE TABLE IF NOT EXISTS media_assets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
product_id UUID REFERENCES products(id) ON DELETE CASCADE,
cad_file_id UUID REFERENCES cad_files(id) ON DELETE SET NULL,
order_line_id UUID REFERENCES order_lines(id) ON DELETE SET NULL,
workflow_run_id UUID REFERENCES workflow_runs(id) ON DELETE SET NULL,
asset_type media_asset_type NOT NULL,
storage_key TEXT NOT NULL,
file_size_bytes BIGINT,
mime_type VARCHAR(100),
width INTEGER,
height INTEGER,
duration_s FLOAT,
render_config JSONB,
is_archived BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
)
""")
op.execute("CREATE INDEX IF NOT EXISTS ix_media_assets_product ON media_assets (product_id)")
op.execute("CREATE INDEX IF NOT EXISTS ix_media_assets_tenant ON media_assets (tenant_id)")
op.execute("CREATE INDEX IF NOT EXISTS ix_media_assets_order_line ON media_assets (order_line_id)")
op.execute("CREATE INDEX IF NOT EXISTS ix_media_assets_asset_type ON media_assets (asset_type)")
op.execute("ALTER TABLE media_assets ENABLE ROW LEVEL SECURITY")
op.execute("""
DO $$ BEGIN
CREATE POLICY tenant_isolation ON media_assets
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
""")
op.execute("""
DO $$ BEGIN
CREATE POLICY admin_bypass ON media_assets
USING (current_setting('app.current_tenant_id', true) = 'bypass');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
""")
def downgrade():
op.drop_table('media_assets')
op.execute("DROP TYPE IF EXISTS media_asset_type")