summaryrefslogtreecommitdiff
path: root/makima/src/db/repository.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/db/repository.rs')
-rw-r--r--makima/src/db/repository.rs38
1 files changed, 36 insertions, 2 deletions
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index 4aa09dc..b5888c9 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -5051,6 +5051,7 @@ pub async fn update_directive_for_owner(
let title = req.title.as_deref().unwrap_or(&current.title);
let goal = req.goal.as_deref().unwrap_or(&current.goal);
+ let goal_changed = goal != current.goal;
let status = req.status.as_deref().unwrap_or(&current.status);
let repository_url = req.repository_url.as_deref().or(current.repository_url.as_deref());
let local_path = req.local_path.as_deref().or(current.local_path.as_deref());
@@ -5066,6 +5067,7 @@ pub async fn update_directive_for_owner(
SET title = $3, goal = $4, status = $5, repository_url = $6, local_path = $7,
base_branch = $8, orchestrator_task_id = $9, pr_url = $10, pr_branch = $11,
reconcile_mode = $12,
+ goal_updated_at = CASE WHEN $13 THEN NOW() ELSE goal_updated_at END,
version = version + 1, updated_at = NOW()
WHERE id = $1 AND owner_id = $2
RETURNING *
@@ -5083,6 +5085,7 @@ pub async fn update_directive_for_owner(
.bind(pr_url)
.bind(pr_branch)
.bind(reconcile_mode)
+ .bind(goal_changed)
.fetch_optional(pool)
.await
.map_err(RepositoryError::Database)?;
@@ -5574,7 +5577,9 @@ pub async fn check_directive_idle(
Ok(result.rows_affected() > 0)
}
-/// Update a directive's goal and bump goal_updated_at. Reactivates if idle.
+/// Update a directive's goal and bump goal_updated_at.
+/// Reactivates idle/paused directives and clears any stale orchestrator task
+/// so that replanning triggers on the next tick.
pub async fn update_directive_goal(
pool: &PgPool,
owner_id: Uuid,
@@ -5586,7 +5591,8 @@ pub async fn update_directive_goal(
UPDATE directives
SET goal = $3,
goal_updated_at = NOW(),
- status = CASE WHEN status = 'idle' THEN 'active' ELSE status END,
+ status = CASE WHEN status IN ('idle', 'paused') THEN 'active' ELSE status END,
+ orchestrator_task_id = NULL,
updated_at = NOW(),
version = version + 1
WHERE id = $1 AND owner_id = $2
@@ -5913,6 +5919,34 @@ pub async fn clear_orchestrator_task(
Ok(())
}
+/// Cancel old planning tasks for a directive.
+/// Marks any non-terminal planning/re-planning tasks as interrupted,
+/// excluding the given new task. Identifies planning tasks by name prefix
+/// ("Plan: " or "Re-plan: ") to avoid cancelling completion/verification tasks.
+pub async fn cancel_old_planning_tasks(
+ pool: &PgPool,
+ directive_id: Uuid,
+ exclude_task_id: Uuid,
+) -> Result<u64, sqlx::Error> {
+ let result = sqlx::query(
+ r#"
+ UPDATE tasks
+ SET status = 'interrupted',
+ completed_at = NOW(),
+ updated_at = NOW()
+ WHERE directive_id = $1
+ AND id != $2
+ AND (name LIKE 'Plan: %' OR name LIKE 'Re-plan: %')
+ AND status NOT IN ('completed', 'failed', 'merged', 'done', 'interrupted')
+ "#,
+ )
+ .bind(directive_id)
+ .bind(exclude_task_id)
+ .execute(pool)
+ .await?;
+ Ok(result.rows_affected())
+}
+
/// Link a task to a step without changing step status.
pub async fn link_task_to_step(
pool: &PgPool,