7706c514c8
- 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>
74 lines
2.6 KiB
Python
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")
|