diff options
Diffstat (limited to 'makima/src/db/repository.rs')
| -rw-r--r-- | makima/src/db/repository.rs | 123 |
1 files changed, 121 insertions, 2 deletions
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 323e74e..358ab48 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -4991,7 +4991,8 @@ pub async fn list_directives_for_owner( r#" SELECT d.id, d.owner_id, d.title, d.goal, d.status, d.repository_url, - d.orchestrator_task_id, d.version, d.created_at, d.updated_at, + d.orchestrator_task_id, d.pr_url, d.completion_task_id, + d.version, d.created_at, d.updated_at, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id), 0) as total_steps, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'completed'), 0) as completed_steps, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'running'), 0) as running_steps, @@ -5043,12 +5044,15 @@ pub async fn update_directive_for_owner( let local_path = req.local_path.as_deref().or(current.local_path.as_deref()); let base_branch = req.base_branch.as_deref().or(current.base_branch.as_deref()); let orchestrator_task_id = req.orchestrator_task_id.or(current.orchestrator_task_id); + let pr_url = req.pr_url.as_deref().or(current.pr_url.as_deref()); + let pr_branch = req.pr_branch.as_deref().or(current.pr_branch.as_deref()); let result = sqlx::query_as::<_, Directive>( r#" UPDATE directives SET title = $3, goal = $4, status = $5, repository_url = $6, local_path = $7, - base_branch = $8, orchestrator_task_id = $9, version = version + 1, updated_at = NOW() + base_branch = $8, orchestrator_task_id = $9, pr_url = $10, pr_branch = $11, + version = version + 1, updated_at = NOW() WHERE id = $1 AND owner_id = $2 RETURNING * "#, @@ -5062,6 +5066,8 @@ pub async fn update_directive_for_owner( .bind(local_path) .bind(base_branch) .bind(orchestrator_task_id) + .bind(pr_url) + .bind(pr_branch) .fetch_optional(pool) .await .map_err(RepositoryError::Database)?; @@ -5096,6 +5102,119 @@ pub async fn delete_directive_for_owner( } // ============================================================================= +// Directive Completion Helpers +// ============================================================================= + +/// Row type for completed step tasks. +#[derive(Debug, Clone, sqlx::FromRow)] +pub struct CompletedStepTask { + pub step_name: String, + pub task_id: Uuid, + pub task_name: String, +} + +/// Row type for directive completion task status check. +#[derive(Debug, Clone, sqlx::FromRow)] +pub struct DirectiveCompletionCheck { + pub directive_id: Uuid, + pub completion_task_id: Uuid, + pub task_status: String, + pub pr_url: Option<String>, +} + +/// Get idle directives that need a completion task spawned. +/// Conditions: status = 'idle', no completion_task_id, has repository_url, +/// and has at least one completed step with a task_id. +pub async fn get_idle_directives_needing_completion( + pool: &PgPool, +) -> Result<Vec<Directive>, sqlx::Error> { + sqlx::query_as::<_, Directive>( + r#" + SELECT d.* + FROM directives d + WHERE d.status = 'idle' + AND d.completion_task_id IS NULL + AND d.repository_url IS NOT NULL + AND EXISTS ( + SELECT 1 FROM directive_steps ds + WHERE ds.directive_id = d.id + AND ds.status = 'completed' + AND ds.task_id IS NOT NULL + ) + "#, + ) + .fetch_all(pool) + .await +} + +/// Get directives with active completion tasks, joined with task status. +pub async fn get_completion_tasks_to_check( + pool: &PgPool, +) -> Result<Vec<DirectiveCompletionCheck>, sqlx::Error> { + sqlx::query_as::<_, DirectiveCompletionCheck>( + r#" + SELECT d.id as directive_id, d.completion_task_id, t.status as task_status, d.pr_url + FROM directives d + JOIN tasks t ON t.id = d.completion_task_id + WHERE d.completion_task_id IS NOT NULL + "#, + ) + .fetch_all(pool) + .await +} + +/// Assign a completion task to a directive. +pub async fn assign_completion_task( + pool: &PgPool, + directive_id: Uuid, + task_id: Uuid, +) -> Result<(), sqlx::Error> { + sqlx::query( + r#"UPDATE directives SET completion_task_id = $2, updated_at = NOW() WHERE id = $1"#, + ) + .bind(directive_id) + .bind(task_id) + .execute(pool) + .await?; + Ok(()) +} + +/// Clear the completion task from a directive. +pub async fn clear_completion_task( + pool: &PgPool, + directive_id: Uuid, +) -> Result<(), sqlx::Error> { + sqlx::query( + r#"UPDATE directives SET completion_task_id = NULL, updated_at = NOW() WHERE id = $1"#, + ) + .bind(directive_id) + .execute(pool) + .await?; + Ok(()) +} + +/// Get completed step tasks for a directive (steps that have completed with an assigned task). +pub async fn get_completed_step_tasks( + pool: &PgPool, + directive_id: Uuid, +) -> Result<Vec<CompletedStepTask>, sqlx::Error> { + sqlx::query_as::<_, CompletedStepTask>( + r#" + SELECT ds.name as step_name, ds.task_id, t.name as task_name + FROM directive_steps ds + JOIN tasks t ON t.id = ds.task_id + WHERE ds.directive_id = $1 + AND ds.status = 'completed' + AND ds.task_id IS NOT NULL + ORDER BY ds.order_index, ds.created_at + "#, + ) + .bind(directive_id) + .fetch_all(pool) + .await +} + +// ============================================================================= // Directive Step CRUD // ============================================================================= |
