feat: Implement timeout handling and background processing for update feature
This commit is contained in:
parent
c97301728c
commit
f4eb511a1c
7 changed files with 849 additions and 94 deletions
80
UPDATE_FIX_SUMMARY.md
Normal file
80
UPDATE_FIX_SUMMARY.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# Update Feature Fixes - Final Summary
|
||||
|
||||
## Problem Identified
|
||||
The update feature was causing the application to hang indefinitely when clicked. The issue had two components:
|
||||
|
||||
1. **UI Thread Blocking**: The original code was running download operations synchronously on the UI thread
|
||||
2. **Network Timeout Issues**: Even with timeouts set, the socket-level network calls would hang indefinitely if the server didn't respond
|
||||
|
||||
## Solutions Implemented
|
||||
|
||||
### 1. Background Threading (First Fix)
|
||||
- Created `UpdateDownloadWorker` class to run download operations in a background thread
|
||||
- Moved blocking network calls off the UI thread
|
||||
- This prevents the UI from freezing while waiting for network operations
|
||||
|
||||
### 2. Aggressive Timeout Strategy (Second Fix)
|
||||
Applied timeouts at multiple levels to ensure the app never hangs:
|
||||
|
||||
#### A. Socket-Level Timeout (Most Important)
|
||||
- **File**: `src/webdrop_bridge/core/updater.py`
|
||||
- Reduced `urlopen()` timeout from 10 seconds to **5 seconds**
|
||||
- This is the first line of defense against hanging socket connections
|
||||
- Applied in `_fetch_release()` method
|
||||
|
||||
#### B. Asyncio-Level Timeout
|
||||
- **File**: `src/webdrop_bridge/ui/main_window.py` and `src/webdrop_bridge/core/updater.py`
|
||||
- `UpdateCheckWorker`: 10-second timeout on entire check operation
|
||||
- `UpdateDownloadWorker`: 300-second timeout on download, 30-second on verification
|
||||
- `check_for_updates()`: 8-second timeout on async executor
|
||||
- These catch any remaining hangs in the asyncio operations
|
||||
|
||||
#### C. Qt-Level Timeout (Final Safety Net)
|
||||
- **File**: `src/webdrop_bridge/ui/main_window.py`
|
||||
- Update check: **30-second QTimer** safety timeout (`_run_async_check()`)
|
||||
- Download: **10-minute QTimer** safety timeout (`_perform_update_async()`)
|
||||
- If nothing else works, Qt's event loop will forcefully close the operation
|
||||
|
||||
### 3. Error Handling Improvements
|
||||
- Added proper exception handling for `asyncio.TimeoutError`
|
||||
- Better logging to identify where hangs occur
|
||||
- User-friendly error messages like "no server response" or "Operation timed out"
|
||||
- Graceful degradation: operations fail fast instead of hanging
|
||||
|
||||
## Timeout Hierarchy (in seconds)
|
||||
```
|
||||
Update Check Flow:
|
||||
QTimer safety net: 30s ─┐
|
||||
├─ Asyncio timeout: 10s ─┐
|
||||
├─ Socket timeout: 5s (first to trigger)
|
||||
Download Flow:
|
||||
QTimer safety net: 600s ─┐
|
||||
├─ Asyncio timeout: 300s ─┐
|
||||
├─ Socket timeout: 5s (first to trigger)
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
1. **src/webdrop_bridge/ui/main_window.py**
|
||||
- Updated `UpdateCheckWorker.run()` with timeout handling
|
||||
- Updated `UpdateDownloadWorker.run()` with timeout handling
|
||||
- Added QTimer safety timeouts in `_run_async_check()` and `_perform_update_async()`
|
||||
- Proper event loop cleanup in finally blocks
|
||||
|
||||
2. **src/webdrop_bridge/core/updater.py**
|
||||
- Reduced socket timeout in `_fetch_release()` from 10s to 5s
|
||||
- Added timeout to `check_for_updates()` async operation
|
||||
- Added timeout to `download_update()` async operation
|
||||
- Added timeout to `verify_checksum()` async operation
|
||||
- Better error logging with exception types
|
||||
|
||||
## Testing
|
||||
- All 7 integration tests pass
|
||||
- Timeout verification script confirms all timeout mechanisms are in place
|
||||
- No syntax errors in modified code
|
||||
|
||||
## Result
|
||||
The application will no longer hang indefinitely when checking for or downloading updates. Instead:
|
||||
- Operations timeout quickly (5-30 seconds depending on operation type)
|
||||
- User gets clear feedback about what went wrong
|
||||
- User can retry or cancel without force-killing the app
|
||||
- Background threads are properly cleaned up to avoid resource leaks
|
||||
Loading…
Add table
Add a link
Reference in a new issue