"""distributed lean workstation agent phase 2 durable jobs Revision ID: 20260822_lean_agent_p2 Revises: 20260822_lean_agent_p1 Create Date: 2026-08-22 """ from alembic import op import sqlalchemy as sa revision = "20260822_lean_agent_p2" down_revision = "20260822_lean_agent_p1" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "erp_agent_jobs", sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True), sa.Column("job_uuid", sa.String(length=64), nullable=False), sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False), sa.Column("branch_id", sa.Integer(), sa.ForeignKey("branches.id", ondelete="SET NULL"), nullable=True), sa.Column("storage_node_id", sa.Integer(), sa.ForeignKey("branch_storage_nodes.id", ondelete="CASCADE"), nullable=False), sa.Column("workstation_agent_id", sa.Integer(), sa.ForeignKey("erp_workstation_agents.id", ondelete="CASCADE"), nullable=False), sa.Column("action", sa.String(length=120), nullable=False), sa.Column("payload_json", sa.Text(), nullable=False, server_default="{}"), sa.Column("idempotency_key", sa.String(length=200), nullable=True), sa.Column("status", sa.String(length=30), nullable=False, server_default="queued"), sa.Column("priority", sa.Integer(), nullable=False, server_default="5"), sa.Column("max_attempts", sa.Integer(), nullable=False, server_default="3"), sa.Column("attempts", sa.Integer(), nullable=False, server_default="0"), sa.Column("last_error", sa.Text(), nullable=True), sa.Column("result_json", sa.Text(), nullable=True), sa.Column("created_by_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True), sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False), sa.Column("updated_at_utc", sa.DateTime(timezone=True), nullable=False), sa.Column("claimed_at_utc", sa.DateTime(timezone=True), nullable=True), sa.Column("lease_expires_at_utc", sa.DateTime(timezone=True), nullable=True), sa.Column("agent_completed_at_utc", sa.DateTime(timezone=True), nullable=True), sa.Column("completed_at_utc", sa.DateTime(timezone=True), nullable=True), sa.Column("failed_at_utc", sa.DateTime(timezone=True), nullable=True), sa.Column("cancelled_at_utc", sa.DateTime(timezone=True), nullable=True), sa.UniqueConstraint("job_uuid", name="uq_erp_agent_jobs_uuid"), sa.UniqueConstraint("workstation_agent_id", "idempotency_key", name="uq_erp_agent_jobs_workstation_idempotency"), ) for name, cols in [ ("ix_erp_agent_jobs_job_uuid", ["job_uuid"]), ("ix_erp_agent_jobs_tenant_id", ["tenant_id"]), ("ix_erp_agent_jobs_branch_id", ["branch_id"]), ("ix_erp_agent_jobs_storage_node_id", ["storage_node_id"]), ("ix_erp_agent_jobs_workstation_agent_id", ["workstation_agent_id"]), ("ix_erp_agent_jobs_action", ["action"]), ("ix_erp_agent_jobs_idempotency_key", ["idempotency_key"]), ("ix_erp_agent_jobs_status", ["status"]), ("ix_erp_agent_jobs_priority", ["priority"]), ("ix_erp_agent_jobs_created_by_user_id", ["created_by_user_id"]), ("ix_erp_agent_jobs_created_at_utc", ["created_at_utc"]), ("ix_erp_agent_jobs_claimed_at_utc", ["claimed_at_utc"]), ("ix_erp_agent_jobs_lease_expires_at_utc", ["lease_expires_at_utc"]), ("ix_erp_agent_jobs_completed_at_utc", ["completed_at_utc"]), ("ix_erp_agent_jobs_failed_at_utc", ["failed_at_utc"]), ("ix_erp_agent_jobs_cancelled_at_utc", ["cancelled_at_utc"]), ]: op.create_index(name, "erp_agent_jobs", cols) op.create_table( "erp_agent_job_events", sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True), sa.Column("job_id", sa.Integer(), sa.ForeignKey("erp_agent_jobs.id", ondelete="CASCADE"), nullable=False), sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False), sa.Column("branch_id", sa.Integer(), sa.ForeignKey("branches.id", ondelete="SET NULL"), nullable=True), sa.Column("workstation_agent_id", sa.Integer(), sa.ForeignKey("erp_workstation_agents.id", ondelete="CASCADE"), nullable=False), sa.Column("event_type", sa.String(length=40), nullable=False), sa.Column("detail", sa.Text(), nullable=True), sa.Column("actor_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True), sa.Column("occurred_at_utc", sa.DateTime(timezone=True), nullable=False), ) for name, cols in [ ("ix_erp_agent_job_events_job_id", ["job_id"]), ("ix_erp_agent_job_events_tenant_id", ["tenant_id"]), ("ix_erp_agent_job_events_branch_id", ["branch_id"]), ("ix_erp_agent_job_events_workstation_agent_id", ["workstation_agent_id"]), ("ix_erp_agent_job_events_event_type", ["event_type"]), ("ix_erp_agent_job_events_actor_user_id", ["actor_user_id"]), ("ix_erp_agent_job_events_occurred_at_utc", ["occurred_at_utc"]), ]: op.create_index(name, "erp_agent_job_events", cols) def downgrade() -> None: op.drop_table("erp_agent_job_events") op.drop_table("erp_agent_jobs")