fix(backend): prevent db lock reentrancy in orchestrator notifications
This commit is contained in:
parent
7f7e066e7c
commit
ce37ce9ea0
2 changed files with 40 additions and 20 deletions
|
|
@ -24,32 +24,50 @@ pub fn get_ticket_result(
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn retry_ticket(state: State<'_, AppState>, ticket_id: String) -> Result<(), AppError> {
|
pub fn retry_ticket(state: State<'_, AppState>, ticket_id: String) -> Result<(), AppError> {
|
||||||
let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
|
let active_worktree_cleanup: Option<(crate::models::worktree::Worktree, String)> = {
|
||||||
let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?;
|
let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
|
||||||
|
let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?;
|
||||||
|
|
||||||
if ticket.status != "Error" && ticket.status != "Done" && ticket.status != "Cancelled" {
|
if ticket.status != "Error" && ticket.status != "Done" && ticket.status != "Cancelled" {
|
||||||
return Err(AppError::from(format!(
|
return Err(AppError::from(format!(
|
||||||
"Cannot retry ticket with status '{}'",
|
"Cannot retry ticket with status '{}'",
|
||||||
ticket.status
|
ticket.status
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessedTicket::update_status(&conn, &ticket_id, "Pending")?;
|
ProcessedTicket::update_status(&conn, &ticket_id, "Pending")?;
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"UPDATE processed_tickets SET analyst_report = NULL, developer_report = NULL, \
|
"UPDATE processed_tickets SET analyst_report = NULL, developer_report = NULL, \
|
||||||
worktree_path = NULL, branch_name = NULL, processed_at = NULL WHERE id = ?1",
|
worktree_path = NULL, branch_name = NULL, processed_at = NULL WHERE id = ?1",
|
||||||
rusqlite::params![ticket_id],
|
rusqlite::params![ticket_id],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(wt) = Worktree::get_by_ticket_id(&conn, &ticket_id)? {
|
let cleanup_target = if let Some(wt) = Worktree::get_by_ticket_id(&conn, &ticket_id)? {
|
||||||
|
if wt.status == "Active" {
|
||||||
|
let project = crate::models::project::Project::get_by_id(&conn, &ticket.project_id)?;
|
||||||
|
Some((wt, project.path))
|
||||||
|
} else {
|
||||||
|
Some((wt, String::new()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
cleanup_target
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((wt, project_path)) = &active_worktree_cleanup {
|
||||||
if wt.status == "Active" {
|
if wt.status == "Active" {
|
||||||
let project = crate::models::project::Project::get_by_id(&conn, &ticket.project_id)?;
|
|
||||||
let _ = crate::services::worktree_manager::delete_worktree(
|
let _ = crate::services::worktree_manager::delete_worktree(
|
||||||
&project.path,
|
project_path,
|
||||||
&wt.path,
|
&wt.path,
|
||||||
&wt.branch_name,
|
&wt.branch_name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((wt, _)) = active_worktree_cleanup {
|
||||||
|
let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
|
||||||
Worktree::delete(&conn, &wt.id)?;
|
Worktree::delete(&conn, &wt.id)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -743,9 +743,11 @@ async fn process_ticket(
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let conn = db.lock().map_err(|e| format!("DB lock: {}", e))?;
|
{
|
||||||
ProcessedTicket::update_status(&conn, &ticket.id, "Done")
|
let conn = db.lock().map_err(|e| format!("DB lock: {}", e))?;
|
||||||
.map_err(|e| format!("update_status: {}", e))?;
|
ProcessedTicket::update_status(&conn, &ticket.id, "Done")
|
||||||
|
.map_err(|e| format!("update_status: {}", e))?;
|
||||||
|
}
|
||||||
let _ = app_handle.emit(
|
let _ = app_handle.emit(
|
||||||
"ticket-processing-done",
|
"ticket-processing-done",
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue