mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
60 lines
2.2 KiB
Python
60 lines
2.2 KiB
Python
"""Per-task and per-project cost budgets (feature-flagged, default off).
|
|||
|
|
|
||
|
|
``tasks.budget_usd`` caps one task's own accumulated agent-spawn spend;
|
||
|
|
``projects.monthly_budget_usd`` caps a project's calendar-month spend across
|
||
|
|
all its tasks. Both nullable and additive — null means "no cap" and is a pure
|
||
|
|
no-op regardless of ``ROBOCO_TASK_BUDGETS_ENABLED`` (the flag itself gates
|
||
|
|
whether the caps are ever consulted at all). Mirrors the ``ci_watch_enabled``
|
||
|
|
per-project opt-in shape (migration 048): the column exists unconditionally,
|
||
|
|
the feature flag decides whether anything reads it.
|
||
|
|
|
||
|
|
``ix_agent_spawn_sessions_task_id`` rides along: both the claim-time monthly-
|
||
|
|
spend query (``TaskService.project_month_spend_usd``) and the orchestrator's
|
||
|
|
per-tick task-spend sweep (``_task_spend_usd``) filter this table by
|
||
|
|
``task_id`` with no existing index — an unbounded per-row scan every minute
|
||
|
|
once the flag is armed. Added here rather than a separate migration since it
|
||
|
|
exists to serve these same two new read paths.
|
||
|
|
|
||
|
|
Revision ID: 080_task_project_budgets
|
||
|
|
Revises: 079_notification_backoff
|
||
|
|
Create Date: 2026-07-22
|
||
|
|
|
||
|
|
NOTE: down_revision was re-chained from 078_project_codegen_command to
|
||
|
|
079_notification_backoff (PR #652 landed first at integration) — the
|
||
|
|
079_task_project_budgets -> 080_task_project_budgets rename + re-chain is
|
||
|
|
exactly the "may be re-chained at integration" case flagged in the original
|
||
|
|
docstring, not a fork of the tree.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import sqlalchemy as sa
|
||
|
|
from alembic import op
|
||
|
|
|
||
|
|
revision = "080_task_project_budgets"
|
||
|
|
down_revision = "079_notification_backoff"
|
||
|
|
branch_labels: dict[str, str] | None = None
|
||
|
|
depends_on: dict[str, str] | None = None
|
||
|
|
|
||
|
|
|
||
|
|
def upgrade() -> None:
|
||
|
|
op.add_column(
|
||
|
|
"tasks",
|
||
|
|
sa.Column("budget_usd", sa.Float(), nullable=True),
|
||
|
|
)
|
||
|
|
op.add_column(
|
||
|
|
"projects",
|
||
|
|
sa.Column("monthly_budget_usd", sa.Float(), nullable=True),
|
||
|
|
)
|
||
|
|
op.create_index(
|
||
|
|
"ix_agent_spawn_sessions_task_id",
|
||
|
|
"agent_spawn_sessions",
|
||
|
|
["task_id"],
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def downgrade() -> None:
|
||
|
|
op.drop_index("ix_agent_spawn_sessions_task_id", table_name="agent_spawn_sessions")
|
||
|
|
op.drop_column("projects", "monthly_budget_usd")
|
||
|
|
op.drop_column("tasks", "budget_usd")
|