Skip to content
Merged
24 changes: 13 additions & 11 deletions backend/alembic/versions/202607161200_unify_runtime_group_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,6 @@
},
"agent_run_events": {
"uq_agent_run_events_run_idempotency": ("run_id", "idempotency_key"),
"uq_agent_run_events_checkpoint_type": (
"run_id",
"source_checkpoint_id",
"event_type",
),
},
"agent_tool_executions": {
"uq_agent_tool_executions_run_tool_call": ("run_id", "tool_call_id")
Expand Down Expand Up @@ -289,6 +284,10 @@
"agent_run_events",
("tenant_id", "event_type", "created_at"),
),
"uq_agent_run_events_checkpoint_type_non_delivery": (
"agent_run_events",
("run_id", "source_checkpoint_id", "event_type"),
),
"ix_agent_tool_executions_tenant_status_started": (
"agent_tool_executions",
("tenant_id", "status", "started_at"),
Expand Down Expand Up @@ -1978,12 +1977,6 @@ def _create_agent_run_events() -> None:
"idempotency_key",
name="uq_agent_run_events_run_idempotency",
),
sa.UniqueConstraint(
"run_id",
"source_checkpoint_id",
"event_type",
name="uq_agent_run_events_checkpoint_type",
),
)


Expand Down Expand Up @@ -2235,6 +2228,15 @@ def _create_runtime_indexes() -> None:
unique=False,
postgresql_where=sa.text("scheduling_lane_key IS NOT NULL"),
)
op.create_index(
"uq_agent_run_events_checkpoint_type_non_delivery",
"agent_run_events",
["run_id", "source_checkpoint_id", "event_type"],
unique=True,
postgresql_where=sa.text(
"event_type NOT IN ('delivery_succeeded', 'delivery_failed')"
),
)
for name, table_name, columns in (
(
"ix_agent_run_commands_status_claim_created",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Allow distinct delivery receipts from one Runtime checkpoint.

Revision ID: allow_checkpoint_deliveries
Revises: add_agent_model_deleted_at
Create Date: 2026-07-24 13:00:00
"""

from __future__ import annotations

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

revision: str = "allow_checkpoint_deliveries"
down_revision: str | None = "add_agent_model_deleted_at"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


TABLE = "agent_run_events"
OLD_CONSTRAINT = "uq_agent_run_events_checkpoint_type"
NON_DELIVERY_INDEX = "uq_agent_run_events_checkpoint_type_non_delivery"


def _inspector():
return sa.inspect(op.get_bind())


def _constraint_exists(name: str) -> bool:
return name in {constraint["name"] for constraint in _inspector().get_unique_constraints(TABLE)}


def _index_exists(name: str) -> bool:
return name in {index["name"] for index in _inspector().get_indexes(TABLE)}


def upgrade() -> None:
if _constraint_exists(OLD_CONSTRAINT):
op.drop_constraint(OLD_CONSTRAINT, TABLE, type_="unique")

if not _index_exists(NON_DELIVERY_INDEX):
op.create_index(
NON_DELIVERY_INDEX,
TABLE,
["run_id", "source_checkpoint_id", "event_type"],
unique=True,
postgresql_where=sa.text("event_type NOT IN ('delivery_succeeded', 'delivery_failed')"),
)


def downgrade() -> None:
if _index_exists(NON_DELIVERY_INDEX):
op.drop_index(NON_DELIVERY_INDEX, table_name=TABLE)

if not _constraint_exists(OLD_CONSTRAINT):
op.create_unique_constraint(
OLD_CONSTRAINT,
TABLE,
["run_id", "source_checkpoint_id", "event_type"],
)
8 changes: 6 additions & 2 deletions backend/app/models/agent_run_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,15 @@ class AgentRunEvent(Base):
ondelete="CASCADE",
),
UniqueConstraint("run_id", "idempotency_key", name="uq_agent_run_events_run_idempotency"),
UniqueConstraint(
Index(
"uq_agent_run_events_checkpoint_type_non_delivery",
"run_id",
"source_checkpoint_id",
"event_type",
name="uq_agent_run_events_checkpoint_type",
unique=True,
postgresql_where=text(
"event_type NOT IN ('delivery_succeeded', 'delivery_failed')"
),
),
Index("ix_agent_run_events_run_created", "run_id", "created_at"),
Index(
Expand Down
Loading