feat(backend): stop schedules and cancel jobs when archiving a workspace (#7377)

This commit is contained in:
hugocasa
2025-12-15 19:03:28 +01:00
committed by GitHub
parent b3603d8720
commit ebc82dbe58
3 changed files with 111 additions and 2 deletions
@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET enabled = false WHERE workspace_id = $1 AND enabled = true RETURNING path",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
},
"hash": "03669873e4e3b22c737d5170821f677925474aad885bf1c0780bdb978225517e"
}
@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id FROM v2_job_queue WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
},
"hash": "b9c520fdc29b17977bf1c0b30311c536ebea8a76b75cda188ec91fcc0fc274a7"
}
+67 -2
View File
@@ -3327,11 +3327,73 @@ async fn archive_workspace(
authed: ApiAuthed,
) -> Result<String> {
require_admin(authed.is_admin, &authed.username)?;
// Step 1: Disable all schedules and clear their queued jobs
let mut tx = db.begin().await?;
let disabled_schedules = sqlx::query_scalar!(
"UPDATE schedule SET enabled = false WHERE workspace_id = $1 AND enabled = true RETURNING path",
&w_id
)
.fetch_all(&mut *tx)
.await?;
let schedules_count = disabled_schedules.len();
tracing::info!(
"Disabled {} schedules in workspace {}",
schedules_count,
w_id
);
// Clear all schedule-related jobs using the existing clear_schedule function
for schedule_path in &disabled_schedules {
crate::schedule::clear_schedule(&mut tx, schedule_path, &w_id).await?;
}
tx.commit().await?;
// Step 2: Get all remaining queued jobs for this workspace (non-schedule jobs)
let jobs_to_cancel =
sqlx::query_scalar!("SELECT id FROM v2_job_queue WHERE workspace_id = $1", &w_id)
.fetch_all(&db)
.await?;
let jobs_count = jobs_to_cancel.len();
tracing::info!(
"Found {} remaining jobs to cancel in workspace {}",
jobs_count,
w_id
);
// Step 3: Cancel all remaining jobs using the existing cancel_jobs function
let canceled_count = if !jobs_to_cancel.is_empty() {
let axum::Json(canceled_jobs) = crate::jobs::cancel_jobs(
jobs_to_cancel,
&db,
&authed.username,
&w_id,
false, // force_cancel
)
.await?;
let count = canceled_jobs.len();
tracing::info!("Canceled {} jobs in workspace {}", count, w_id);
count
} else {
0
};
// Step 4: Archive the workspace
let mut tx = db.begin().await?;
sqlx::query!("UPDATE workspace SET deleted = true WHERE id = $1", &w_id)
.execute(&mut *tx)
.await?;
let mut audit_params = HashMap::new();
audit_params.insert("disabled_schedules", schedules_count.to_string());
audit_params.insert("canceled_jobs", canceled_count.to_string());
let audit_params_refs: HashMap<&str, &str> =
audit_params.iter().map(|(k, v)| (*k, v.as_str())).collect();
audit_log(
&mut *tx,
&authed,
@@ -3339,12 +3401,15 @@ async fn archive_workspace(
ActionKind::Update,
&w_id,
Some(&authed.email),
None,
Some(audit_params_refs),
)
.await?;
tx.commit().await?;
Ok(format!("Archived workspace {}", &w_id))
Ok(format!(
"Archived workspace {}, disabled {} schedules and canceled {} jobs",
&w_id, schedules_count, canceled_count
))
}
async fn leave_workspace(