refactor container and deployments. scope logic appropriately and remove unused code. (#1351)

This commit is contained in:
Gabriel Gordon-Hall
2025-11-24 18:45:56 +00:00
committed by GitHub
parent 036dd802d8
commit bd93f14090
8 changed files with 289 additions and 369 deletions

View File

@@ -1,4 +1,4 @@
use std::{collections::HashMap, sync::Arc};
use std::sync::Arc;
use anyhow::Error as AnyhowError;
use async_trait::async_trait;
@@ -6,10 +6,8 @@ use axum::response::sse::Event;
use db::{
DBService,
models::{
execution_process::{ExecutionProcess, ExecutionProcessRunReason, ExecutionProcessStatus},
project::{CreateProject, Project},
task::{Task, TaskStatus},
task_attempt::{TaskAttempt, TaskAttemptError},
task_attempt::TaskAttemptError,
},
};
use executors::executors::ExecutorError;
@@ -36,7 +34,7 @@ use services::services::{
use sqlx::{Error as SqlxError, types::Uuid};
use thiserror::Error;
use tokio::sync::{Mutex, RwLock};
use utils::{msg_store::MsgStore, sentry as sentry_utils};
use utils::sentry as sentry_utils;
#[derive(Debug, Clone, Copy, Error)]
#[error("Remote client not configured")]
@@ -82,8 +80,6 @@ pub trait Deployment: Clone + Send + Sync + 'static {
fn user_id(&self) -> &str;
fn shared_types() -> Vec<String>;
fn config(&self) -> &Arc<RwLock<Config>>;
fn db(&self) -> &DBService;
@@ -98,8 +94,6 @@ pub trait Deployment: Clone + Send + Sync + 'static {
fn filesystem(&self) -> &FilesystemService;
fn msg_stores(&self) -> &Arc<RwLock<HashMap<Uuid, Arc<MsgStore>>>>;
fn events(&self) -> &EventService;
fn file_search_cache(&self) -> &Arc<FileSearchCache>;
@@ -163,130 +157,6 @@ pub trait Deployment: Clone + Send + Sync + 'static {
}
}
/// Cleanup executions marked as running in the db, call at startup
async fn cleanup_orphan_executions(&self) -> Result<(), DeploymentError> {
let running_processes = ExecutionProcess::find_running(&self.db().pool).await?;
for process in running_processes {
tracing::info!(
"Found orphaned execution process {} for task attempt {}",
process.id,
process.task_attempt_id
);
// Update the execution process status first
if let Err(e) = ExecutionProcess::update_completion(
&self.db().pool,
process.id,
ExecutionProcessStatus::Failed,
None, // No exit code for orphaned processes
)
.await
{
tracing::error!(
"Failed to update orphaned execution process {} status: {}",
process.id,
e
);
continue;
}
// Capture after-head commit OID (best-effort)
if let Ok(Some(task_attempt)) =
TaskAttempt::find_by_id(&self.db().pool, process.task_attempt_id).await
&& let Some(container_ref) = task_attempt.container_ref
{
let wt = std::path::PathBuf::from(container_ref);
if let Ok(head) = self.git().get_head_info(&wt) {
let _ = ExecutionProcess::update_after_head_commit(
&self.db().pool,
process.id,
&head.oid,
)
.await;
}
}
// Process marked as failed
tracing::info!("Marked orphaned execution process {} as failed", process.id);
// Update task status to InReview for coding agent and setup script failures
if matches!(
process.run_reason,
ExecutionProcessRunReason::CodingAgent
| ExecutionProcessRunReason::SetupScript
| ExecutionProcessRunReason::CleanupScript
) && let Ok(Some(task_attempt)) =
TaskAttempt::find_by_id(&self.db().pool, process.task_attempt_id).await
&& let Ok(Some(task)) = task_attempt.parent_task(&self.db().pool).await
{
match Task::update_status(&self.db().pool, task.id, TaskStatus::InReview).await {
Ok(_) => {
if let Ok(publisher) = self.share_publisher()
&& let Err(err) = publisher.update_shared_task_by_id(task.id).await
{
tracing::warn!(
?err,
"Failed to propagate shared task update for {}",
task.id
);
}
}
Err(e) => {
tracing::error!(
"Failed to update task status to InReview for orphaned attempt: {}",
e
);
}
}
}
}
Ok(())
}
/// Backfill before_head_commit for legacy execution processes.
/// Rules:
/// - If a process has after_head_commit and missing before_head_commit,
/// then set before_head_commit to the previous process's after_head_commit.
/// - If there is no previous process, set before_head_commit to the base branch commit.
async fn backfill_before_head_commits(&self) -> Result<(), DeploymentError> {
let pool = &self.db().pool;
let rows = ExecutionProcess::list_missing_before_context(pool).await?;
for row in rows {
// Skip if no after commit at all (shouldn't happen due to WHERE)
// Prefer previous process after-commit if present
let mut before = row.prev_after_head_commit.clone();
// Fallback to base branch commit OID
if before.is_none() {
let repo_path =
std::path::Path::new(row.git_repo_path.as_deref().unwrap_or_default());
match self
.git()
.get_branch_oid(repo_path, row.target_branch.as_str())
{
Ok(oid) => before = Some(oid),
Err(e) => {
tracing::warn!(
"Backfill: Failed to resolve base branch OID for attempt {} (branch {}): {}",
row.task_attempt_id,
row.target_branch,
e
);
}
}
}
if let Some(before_oid) = before
&& let Err(e) =
ExecutionProcess::update_before_head_commit(pool, row.id, &before_oid).await
{
tracing::warn!(
"Backfill: Failed to update before_head_commit for process {}: {}",
row.id,
e
);
}
}
Ok(())
}
/// Trigger background auto-setup of default projects for new users
async fn trigger_auto_project_setup(&self) {
// soft timeout to give the filesystem search a chance to complete