mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-04 20:05:16 +02:00
fix: make migration 144 idempotent
This commit is contained in:
parent
c44263e3d8
commit
b2b70cfa3e
1 changed files with 66 additions and 30 deletions
|
|
@ -25,34 +25,60 @@ depends_on: str | Sequence[str] | None = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
# ENUM types (PostgreSQL requires types created before tables that use them)
|
# Guard every object so the migration is safe to re-run after a partial
|
||||||
|
# apply (the types/tables outlive a failed run that never advanced
|
||||||
|
# alembic_version). Types must precede the tables that reference them.
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE automation_status AS ENUM (
|
DO $$
|
||||||
'active', 'paused', 'archived'
|
BEGIN
|
||||||
);
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM pg_type WHERE typname = 'automation_status'
|
||||||
|
) THEN
|
||||||
|
CREATE TYPE automation_status AS ENUM (
|
||||||
|
'active', 'paused', 'archived'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE automation_trigger_type AS ENUM (
|
DO $$
|
||||||
'schedule', 'manual'
|
BEGIN
|
||||||
);
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM pg_type WHERE typname = 'automation_trigger_type'
|
||||||
|
) THEN
|
||||||
|
CREATE TYPE automation_trigger_type AS ENUM (
|
||||||
|
'schedule', 'manual'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE automation_run_status AS ENUM (
|
DO $$
|
||||||
'pending', 'running', 'succeeded', 'failed',
|
BEGIN
|
||||||
'cancelled', 'timed_out'
|
IF NOT EXISTS (
|
||||||
);
|
SELECT 1 FROM pg_type WHERE typname = 'automation_run_status'
|
||||||
|
) THEN
|
||||||
|
CREATE TYPE automation_run_status AS ENUM (
|
||||||
|
'pending', 'running', 'succeeded', 'failed',
|
||||||
|
'cancelled', 'timed_out'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
# automations — the editable, versioned automation definition
|
# automations — the editable, versioned automation definition
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE automations (
|
CREATE TABLE IF NOT EXISTS automations (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
search_space_id INTEGER NOT NULL
|
search_space_id INTEGER NOT NULL
|
||||||
REFERENCES searchspaces(id) ON DELETE CASCADE,
|
REFERENCES searchspaces(id) ON DELETE CASCADE,
|
||||||
|
|
@ -69,19 +95,25 @@ def upgrade() -> None:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automations_search_space_id ON automations(search_space_id);"
|
"CREATE INDEX IF NOT EXISTS ix_automations_search_space_id ON automations(search_space_id);"
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automations_created_by_user_id ON automations(created_by_user_id);"
|
"CREATE INDEX IF NOT EXISTS ix_automations_created_by_user_id ON automations(created_by_user_id);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automations_status ON automations(status);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automations_created_at ON automations(created_at);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automations_updated_at ON automations(updated_at);"
|
||||||
)
|
)
|
||||||
op.execute("CREATE INDEX ix_automations_status ON automations(status);")
|
|
||||||
op.execute("CREATE INDEX ix_automations_created_at ON automations(created_at);")
|
|
||||||
op.execute("CREATE INDEX ix_automations_updated_at ON automations(updated_at);")
|
|
||||||
|
|
||||||
# automation_triggers — one row per (automation, trigger-instance) pair
|
# automation_triggers — one row per (automation, trigger-instance) pair
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE automation_triggers (
|
CREATE TABLE IF NOT EXISTS automation_triggers (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
automation_id INTEGER NOT NULL
|
automation_id INTEGER NOT NULL
|
||||||
REFERENCES automations(id) ON DELETE CASCADE,
|
REFERENCES automations(id) ON DELETE CASCADE,
|
||||||
|
|
@ -96,20 +128,22 @@ def upgrade() -> None:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automation_triggers_automation_id ON automation_triggers(automation_id);"
|
"CREATE INDEX IF NOT EXISTS ix_automation_triggers_automation_id ON automation_triggers(automation_id);"
|
||||||
)
|
|
||||||
op.execute("CREATE INDEX ix_automation_triggers_type ON automation_triggers(type);")
|
|
||||||
op.execute(
|
|
||||||
"CREATE INDEX ix_automation_triggers_enabled ON automation_triggers(enabled);"
|
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automation_triggers_created_at ON automation_triggers(created_at);"
|
"CREATE INDEX IF NOT EXISTS ix_automation_triggers_type ON automation_triggers(type);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automation_triggers_enabled ON automation_triggers(enabled);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automation_triggers_created_at ON automation_triggers(created_at);"
|
||||||
)
|
)
|
||||||
# Partial index for the schedule tick: only enabled schedule triggers
|
# Partial index for the schedule tick: only enabled schedule triggers
|
||||||
# with a scheduled next fire are ever scanned for due rows.
|
# with a scheduled next fire are ever scanned for due rows.
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE INDEX ix_automation_triggers_due
|
CREATE INDEX IF NOT EXISTS ix_automation_triggers_due
|
||||||
ON automation_triggers (next_fire_at)
|
ON automation_triggers (next_fire_at)
|
||||||
WHERE enabled = true
|
WHERE enabled = true
|
||||||
AND type = 'schedule'
|
AND type = 'schedule'
|
||||||
|
|
@ -120,7 +154,7 @@ def upgrade() -> None:
|
||||||
# automation_runs — the immutable per-fire execution record
|
# automation_runs — the immutable per-fire execution record
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE automation_runs (
|
CREATE TABLE IF NOT EXISTS automation_runs (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
automation_id INTEGER NOT NULL
|
automation_id INTEGER NOT NULL
|
||||||
REFERENCES automations(id) ON DELETE CASCADE,
|
REFERENCES automations(id) ON DELETE CASCADE,
|
||||||
|
|
@ -140,14 +174,16 @@ def upgrade() -> None:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automation_runs_automation_id ON automation_runs(automation_id);"
|
"CREATE INDEX IF NOT EXISTS ix_automation_runs_automation_id ON automation_runs(automation_id);"
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automation_runs_trigger_id ON automation_runs(trigger_id);"
|
"CREATE INDEX IF NOT EXISTS ix_automation_runs_trigger_id ON automation_runs(trigger_id);"
|
||||||
)
|
)
|
||||||
op.execute("CREATE INDEX ix_automation_runs_status ON automation_runs(status);")
|
|
||||||
op.execute(
|
op.execute(
|
||||||
"CREATE INDEX ix_automation_runs_created_at ON automation_runs(created_at);"
|
"CREATE INDEX IF NOT EXISTS ix_automation_runs_status ON automation_runs(status);"
|
||||||
|
)
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS ix_automation_runs_created_at ON automation_runs(created_at);"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue