Add durable claimable ops_runs table, emit dual-write on TaskSpec, REST claim/lease/complete/fail API, ops status visibility, and consumer docs aligned with ACT-ADR-005. T07 railiance rollout remains deploy-side.
95 lines
3.2 KiB
Python
95 lines
3.2 KiB
Python
"""create_ops_runs
|
|
|
|
Revision ID: 0007
|
|
Revises: 0006
|
|
Create Date: 2026-08-03
|
|
|
|
ACTIVITY-WP-0026 / ACT-ADR-005 — claimable ops run queue.
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
revision: str = "0007"
|
|
down_revision: Union[str, Sequence[str], None] = "0006"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"ops_runs",
|
|
sa.Column(
|
|
"id",
|
|
sa.UUID(),
|
|
nullable=False,
|
|
server_default=sa.text("gen_random_uuid()"),
|
|
),
|
|
sa.Column("activity_definition_id", sa.UUID(), nullable=False),
|
|
sa.Column("idempotency_key", sa.Text(), nullable=False),
|
|
sa.Column("target_repo", sa.Text(), nullable=True),
|
|
sa.Column("title", sa.Text(), nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=False, server_default=""),
|
|
sa.Column(
|
|
"labels",
|
|
postgresql.JSONB(astext_type=sa.Text()),
|
|
nullable=False,
|
|
server_default=sa.text("'[]'::jsonb"),
|
|
),
|
|
sa.Column("priority", sa.Text(), nullable=False, server_default="medium"),
|
|
sa.Column("state", sa.Text(), nullable=False, server_default="open"),
|
|
sa.Column("claim_owner", sa.Text(), nullable=True),
|
|
sa.Column("lease_until", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("attempt", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("source_type", sa.Text(), nullable=False),
|
|
sa.Column("source_id", sa.Text(), nullable=False),
|
|
sa.Column("triggering_event_id", sa.Text(), nullable=False),
|
|
sa.Column("approach_hint", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"result",
|
|
postgresql.JSONB(astext_type=sa.Text()),
|
|
nullable=False,
|
|
server_default=sa.text("'{}'::jsonb"),
|
|
),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["activity_definition_id"],
|
|
["activity_definitions.id"],
|
|
ondelete="RESTRICT",
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint("idempotency_key", name="uq_ops_runs_idempotency_key"),
|
|
)
|
|
op.create_index("idx_ops_runs_state", "ops_runs", ["state"])
|
|
op.create_index("idx_ops_runs_lease", "ops_runs", ["lease_until"])
|
|
op.create_index(
|
|
"idx_ops_runs_activity",
|
|
"ops_runs",
|
|
["activity_definition_id"],
|
|
)
|
|
op.create_index(
|
|
"idx_ops_runs_trigger",
|
|
"ops_runs",
|
|
["triggering_event_id"],
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("idx_ops_runs_trigger", table_name="ops_runs")
|
|
op.drop_index("idx_ops_runs_activity", table_name="ops_runs")
|
|
op.drop_index("idx_ops_runs_lease", table_name="ops_runs")
|
|
op.drop_index("idx_ops_runs_state", table_name="ops_runs")
|
|
op.drop_table("ops_runs")
|