Skip to content

Commit ee2e7b3

Browse files
authored
Fix handling of database lock error (#139)
* Fix handling of database lock error
1 parent 6924152 commit ee2e7b3

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

src/server/api.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Common API module with shared imports and traits
22
3-
use log::{error, info};
3+
use log::{debug, error, info};
44
use sqlx::sqlite::SqlitePool;
55
use std::sync::Arc;
66
use swagger::ApiError;
@@ -32,6 +32,25 @@ pub fn database_error_with_msg(e: impl std::fmt::Display, msg: impl Into<String>
3232
ApiError(msg_str)
3333
}
3434

35+
/// Like `database_error_with_msg` but preserves "database is locked" in the `ApiError`
36+
/// so that callers can detect lock contention and retry. Does not leak other database
37+
/// error details. Lock contention is logged at debug level (expected transient condition)
38+
/// while other database errors are logged at error level.
39+
pub fn database_lock_aware_error(e: impl std::fmt::Display, msg: impl Into<String>) -> ApiError {
40+
let msg_str = msg.into();
41+
let error_string = e.to_string().to_lowercase();
42+
if error_string.contains("database is locked")
43+
|| error_string.contains("database is busy")
44+
|| error_string.contains("sqlite_busy")
45+
{
46+
debug!("Database lock contention ({}): {}", msg_str, e);
47+
ApiError(format!("{}: database is locked", msg_str))
48+
} else {
49+
error!("Database error ({}): {}", msg_str, e);
50+
ApiError(msg_str)
51+
}
52+
}
53+
3554
pub fn json_parse_error(e: impl std::fmt::Display) -> ApiError {
3655
info!("Failed to parse JSON data: {}", e);
3756
ApiError("Failed to parse event data".to_string())

src/server/http_server.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::server::api::SchedulersApi;
1818
use crate::server::api::UserDataApi;
1919
use crate::server::api::WorkflowActionsApi;
2020
use crate::server::api::WorkflowsApi;
21-
use crate::server::api::database_error_with_msg;
21+
use crate::server::api::{database_error_with_msg, database_lock_aware_error};
2222
use crate::server::api_types::*;
2323
use crate::server::auth::MakeHtpasswdAuthenticator;
2424
use crate::server::authorization::{AccessCheckResult, AuthorizationService};
@@ -613,7 +613,7 @@ where
613613
"Failed to begin transaction for workflow {}: {}",
614614
workflow_id, e
615615
);
616-
return Err(database_error_with_msg(e, "Failed to begin transaction"));
616+
return Err(database_lock_aware_error(e, "Failed to begin transaction"));
617617
}
618618
};
619619

@@ -643,7 +643,10 @@ where
643643
"Database error fetching completed jobs for workflow {}: {}",
644644
workflow_id, e
645645
);
646-
return Err(database_error_with_msg(e, "Failed to fetch completed jobs"));
646+
return Err(database_lock_aware_error(
647+
e,
648+
"Failed to fetch completed jobs",
649+
));
647650
}
648651
};
649652

@@ -713,7 +716,10 @@ where
713716
"Database error marking jobs as processed for workflow {}: {}",
714717
workflow_id, e
715718
);
716-
return Err(database_error_with_msg(e, "Failed to mark jobs processed"));
719+
return Err(database_lock_aware_error(
720+
e,
721+
"Failed to mark jobs processed",
722+
));
717723
}
718724

719725
// Commit the transaction
@@ -722,7 +728,7 @@ where
722728
"Failed to commit transaction for workflow {}: {}",
723729
workflow_id, e
724730
);
725-
return Err(database_error_with_msg(e, "Failed to commit transaction"));
731+
return Err(database_lock_aware_error(e, "Failed to commit transaction"));
726732
}
727733

728734
info!(
@@ -1521,7 +1527,7 @@ impl<C> Server<C> {
15211527
Ok(result) => result.rows_affected(),
15221528
Err(e) => {
15231529
debug!("batch_unblock_jobs_tx: cancellation query failed: {}", e);
1524-
return Err(database_error_with_msg(e, "Failed to update job status"));
1530+
return Err(database_lock_aware_error(e, "Failed to update job status"));
15251531
}
15261532
};
15271533

@@ -1575,7 +1581,7 @@ impl<C> Server<C> {
15751581
Ok(rows) => rows,
15761582
Err(e) => {
15771583
debug!("batch_unblock_jobs_tx: ready query failed: {}", e);
1578-
return Err(database_error_with_msg(e, "Failed to update job status"));
1584+
return Err(database_lock_aware_error(e, "Failed to update job status"));
15791585
}
15801586
};
15811587

0 commit comments

Comments
 (0)