From e9638cc6ed0e5b875f8dc09279d7daf88c5ba32c Mon Sep 17 00:00:00 2001 From: Stefan Hacker Date: Sun, 12 Apr 2026 01:45:52 +0200 Subject: [PATCH] fix: Lock verschwindet nicht mehr - Token-Refresh + laengerer Timeout Problem: Lock verschwand nach 5 Minuten weil: 1. JWT-Token nach 15 Min ablief -> Heartbeat schlug still fehl 2. Server gab Lock nach 5 Min ohne Heartbeat frei Fix Client: - Token-Refresh alle 10 Minuten (vor dem 15-Min-Ablauf) - Aktualisiert den Token in der shared API-Instanz - Heartbeat nutzt immer den aktuellen Token Fix Backend: - Lock-Timeout von 5 auf 15 Minuten erhoeht - Genug Puffer fuer Netzwerk-Probleme oder kurze Unterbrechungen Timeline: 0s -> Lock + Heartbeat alle 10s 600s -> Token-Refresh 900s -> Lock wuerde erst jetzt ablaufen (15 Min ohne Heartbeat) Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/app/models/file_lock.py | 5 +++-- clients/desktop/src-tauri/src/lib.rs | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/backend/app/models/file_lock.py b/backend/app/models/file_lock.py index 8e8698c..09cf7c7 100644 --- a/backend/app/models/file_lock.py +++ b/backend/app/models/file_lock.py @@ -2,8 +2,9 @@ from datetime import datetime, timezone, timedelta from app.extensions import db -# Lock expires after 5 minutes without heartbeat -LOCK_TIMEOUT_MINUTES = 5 +# Lock expires after 15 minutes without heartbeat +# Client sends heartbeat every 10 seconds and refreshes JWT every 10 minutes +LOCK_TIMEOUT_MINUTES = 15 class FileLock(db.Model): diff --git a/clients/desktop/src-tauri/src/lib.rs b/clients/desktop/src-tauri/src/lib.rs index f110cee..9c89628 100644 --- a/clients/desktop/src-tauri/src/lib.rs +++ b/clients/desktop/src-tauri/src/lib.rs @@ -481,19 +481,35 @@ fn start_background_sync( } }); - // Heartbeat every 60s + check if opened files are still in use + // Heartbeat + token refresh + check if opened files still in use let app_hb = app.clone(); let api_hb = api.clone(); std::thread::spawn(move || { let rt = tokio::runtime::Runtime::new().unwrap(); + let mut api_mut = api_hb.clone(); + let mut token_refresh_counter = 0u32; + loop { std::thread::sleep(Duration::from_secs(10)); let state = app_hb.state::(); + // Refresh JWT token every 10 minutes (before 15 min expiry) + token_refresh_counter += 10; + if token_refresh_counter >= 600 { + token_refresh_counter = 0; + if let Ok(new_token) = rt.block_on(api_mut.refresh_token()) { + // Update the shared API instance with new token + if let Some(ref mut api) = *state.api.lock().unwrap() { + api.access_token = new_token; + } + eprintln!("[Auth] Token refreshed"); + } + } + // Heartbeat for locked files let locked = state.locked_files.lock().unwrap().clone(); for file_id in &locked { - let _ = rt.block_on(api_hb.heartbeat(*file_id)); + let _ = rt.block_on(api_mut.heartbeat(*file_id)); } // Check if opened files are still in use by another process