@@ -51,26 +51,25 @@ pub fn update_lock_table(conn: &Connection) {
51
51
/// Called by `rusqlite` if we are waiting too long on a database lock
52
52
/// If called too many times, will assume a deadlock and panic
53
53
pub fn tx_busy_handler ( run_count : i32 ) -> bool {
54
- const TIMEOUT : Duration = Duration :: from_secs ( 300 ) ;
55
54
const AVG_SLEEP_TIME_MS : u64 = 100 ;
56
55
56
+ // Every ~5min, report an error with a backtrace
57
+ // 5min * 60s/min * 1_000ms/s / 100ms
58
+ const ERROR_COUNT : u32 = 3_000 ;
59
+
57
60
// First, check if this is taking unreasonably long. If so, it's probably a deadlock
58
61
let run_count = run_count. unsigned_abs ( ) ;
59
- let approx_time_elapsed =
60
- Duration :: from_millis ( AVG_SLEEP_TIME_MS . saturating_mul ( u64:: from ( run_count) ) ) ;
61
- if approx_time_elapsed > TIMEOUT {
62
- error ! ( "Deadlock detected. Waited {} seconds (estimated) for database lock. Giving up" , approx_time_elapsed. as_secs( ) ;
62
+ if run_count > 0 && run_count % ERROR_COUNT == 0 {
63
+ error ! ( "Deadlock detected. Waited 5 minutes (estimated) for database lock." ;
63
64
"run_count" => run_count,
64
65
"backtrace" => ?Backtrace :: capture( )
65
66
) ;
66
67
for ( k, v) in LOCK_TABLE . lock ( ) . unwrap ( ) . iter ( ) {
67
68
error ! ( "Database '{k}' last locked by {v}" ) ;
68
69
}
69
- panic ! ( "Deadlock in thread {:?}" , thread:: current( ) . name( ) ) ;
70
70
}
71
71
72
72
let mut sleep_time_ms = 2u64 . saturating_pow ( run_count) ;
73
-
74
73
sleep_time_ms = sleep_time_ms. saturating_add ( thread_rng ( ) . gen_range ( 0 ..sleep_time_ms) ) ;
75
74
76
75
if sleep_time_ms > AVG_SLEEP_TIME_MS {
0 commit comments