@@ -38,74 +38,108 @@ def _configure_connection(self, conn):
3838 try :
3939 conn .execute ('PRAGMA foreign_keys = ON' )
4040
41- # Try WAL mode first, fall back to DELETE mode if it fails
42- try :
43- conn .execute ('PRAGMA journal_mode = WAL' )
44- except Exception as wal_error :
45- logger .warning (f"WAL mode failed, using DELETE mode: { wal_error } " )
46- conn .execute ('PRAGMA journal_mode = DELETE' )
47-
4841 # Detect if running on Synology NAS for performance optimizations
4942 is_synology = self ._detect_synology_nas ()
5043 synology_opt_enabled = os .environ .get ('HUNTARR_SYNOLOGY_OPTIMIZATIONS' , 'true' ).lower () == 'true'
5144
5245 if is_synology and synology_opt_enabled :
53- logger .info ("Synology NAS detected - applying performance optimizations for network file systems" )
54- # Synology-optimized settings for network file system performance
55- conn .execute ('PRAGMA synchronous = NORMAL' ) # Much faster on NFS/CIFS, still safe with WAL
56- conn .execute ('PRAGMA cache_size = -40960' ) # 40MB cache for better performance on Synology
57- conn .execute ('PRAGMA temp_store = MEMORY' ) # Store temp tables in memory
58- conn .execute ('PRAGMA busy_timeout = 30000' ) # 30 seconds for Synology I/O
59- conn .execute ('PRAGMA mmap_size = 134217728' ) # 128MB memory map optimized for Synology
46+ logger .info ("Synology NAS detected - applying aggressive performance optimizations for network file systems" )
47+
48+ # CRITICAL: Try WAL mode first, but fall back to DELETE mode if it fails on network shares
49+ try :
50+ conn .execute ('PRAGMA journal_mode = WAL' )
51+ # Test if WAL mode actually works on this network file system
52+ result = conn .execute ('PRAGMA journal_mode' ).fetchone ()
53+ if result and result [0 ] != 'wal' :
54+ logger .warning ("WAL mode failed on network file system, switching to DELETE mode for Synology compatibility" )
55+ conn .execute ('PRAGMA journal_mode = DELETE' )
56+ except Exception as wal_error :
57+ logger .warning (f"WAL mode failed on Synology network share, using DELETE mode: { wal_error } " )
58+ conn .execute ('PRAGMA journal_mode = DELETE' )
59+
60+ # Aggressive Synology-optimized settings for network file system performance
61+ conn .execute ('PRAGMA synchronous = OFF' ) # Most aggressive - no FSYNC waits for maximum performance
62+ conn .execute ('PRAGMA cache_size = -65536' ) # 64MB cache (doubled from 40MB) for better performance
63+ conn .execute ('PRAGMA temp_store = MEMORY' ) # Store temp tables in memory
64+ conn .execute ('PRAGMA busy_timeout = 60000' ) # 60 seconds for Synology I/O (increased from 30s)
65+ conn .execute ('PRAGMA mmap_size = 268435456' ) # 256MB memory map for better performance
66+ conn .execute ('PRAGMA page_size = 32768' ) # Larger page size for network shares (32KB)
67+
68+ # Additional Synology-specific optimizations
69+ conn .execute ('PRAGMA locking_mode = EXCLUSIVE' ) # Exclusive locking for single-user scenarios
70+ conn .execute ('PRAGMA count_changes = OFF' ) # Disable change counting for performance
71+ conn .execute ('PRAGMA legacy_file_format = OFF' ) # Use modern file format
72+ conn .execute ('PRAGMA reverse_unordered_selects = OFF' ) # Consistent query results
73+
6074 else :
6175 if is_synology and not synology_opt_enabled :
6276 logger .info ("Synology NAS detected but optimizations disabled via HUNTARR_SYNOLOGY_OPTIMIZATIONS=false" )
77+
78+ # Try WAL mode first, fall back to DELETE mode if it fails
79+ try :
80+ conn .execute ('PRAGMA journal_mode = WAL' )
81+ except Exception as wal_error :
82+ logger .warning (f"WAL mode failed, using DELETE mode: { wal_error } " )
83+ conn .execute ('PRAGMA journal_mode = DELETE' )
84+
6385 # Standard settings for Docker rebuild resilience and corruption prevention
64- conn .execute ('PRAGMA synchronous = FULL ' ) # Maximum durability for Docker environments
65- conn .execute ('PRAGMA cache_size = -32000' ) # 32MB cache for better performance
66- conn .execute ('PRAGMA temp_store = MEMORY' ) # Store temp tables in memory
67- conn .execute ('PRAGMA busy_timeout = 60000 ' ) # 60 seconds for Docker I/O delays
86+ conn .execute ('PRAGMA synchronous = NORMAL ' ) # Balanced durability/performance for non-Synology
87+ conn .execute ('PRAGMA cache_size = -32768' ) # 32MB cache for better performance
88+ conn .execute ('PRAGMA temp_store = MEMORY' ) # Store temp tables in memory
89+ conn .execute ('PRAGMA busy_timeout = 30000 ' ) # 30 seconds for Docker I/O delays
6890
6991 # Skip mmap on Windows if it causes issues, but use it elsewhere for performance
7092 import platform
7193 if platform .system () != "Windows" :
72- conn .execute ('PRAGMA mmap_size = 268435456 ' ) # 256MB memory map
94+ conn .execute ('PRAGMA mmap_size = 134217728 ' ) # 128MB memory map
7395
7496 # Common settings for all platforms
75- conn .execute ('PRAGMA auto_vacuum = INCREMENTAL' ) # Incremental vacuum for maintenance
76- conn .execute ('PRAGMA secure_delete = ON' ) # Secure deletion to prevent data recovery
97+ conn .execute ('PRAGMA auto_vacuum = INCREMENTAL' ) # Incremental vacuum for maintenance
98+ conn .execute ('PRAGMA secure_delete = OFF' ) # Disable for performance (was ON)
99+ conn .execute ('PRAGMA read_uncommitted = ON' ) # Allow dirty reads for better concurrency
100+
101+ # Additional corruption prevention measures (only if not in aggressive Synology mode)
102+ if not (is_synology and synology_opt_enabled ):
103+ conn .execute ('PRAGMA cell_size_check = ON' ) # Enable cell size validation
104+ conn .execute ('PRAGMA integrity_check' ) # Verify database integrity on connection
77105
78- # Additional corruption prevention measures
79- conn .execute ('PRAGMA cell_size_check = ON' ) # Enable cell size validation
80- conn .execute ('PRAGMA integrity_check' ) # Verify database integrity on connection
81- conn .execute ('PRAGMA optimize' ) # Optimize statistics and indexes
82- conn .execute ('PRAGMA application_id = 1751013204' ) # Set unique application ID for Huntarr
106+ conn .execute ('PRAGMA optimize' ) # Optimize statistics and indexes
107+ conn .execute ('PRAGMA application_id = 1751013204' ) # Set unique application ID for Huntarr
83108
84109 # Enhanced checkpoint settings for WAL mode
85110 result = conn .execute ('PRAGMA journal_mode' ).fetchone ()
86111 if result and result [0 ] == 'wal' :
87112 if is_synology and synology_opt_enabled :
88- # More aggressive checkpointing for Synology
89- conn .execute ('PRAGMA wal_autocheckpoint = 1000 ' ) # Less frequent checkpoints for performance
90- conn .execute ('PRAGMA journal_size_limit = 134217728 ' ) # 128MB journal size limit
113+ # Very aggressive checkpointing for Synology network shares
114+ conn .execute ('PRAGMA wal_autocheckpoint = 2000 ' ) # Much less frequent checkpoints
115+ conn .execute ('PRAGMA journal_size_limit = 268435456 ' ) # 256MB journal size limit
91116 else :
92117 # Conservative checkpointing for other systems
93- conn .execute ('PRAGMA wal_autocheckpoint = 500' ) # More frequent checkpoints for Docker
94- conn .execute ('PRAGMA journal_size_limit = 67108864' ) # 64MB journal size limit
95- conn .execute ('PRAGMA wal_checkpoint(TRUNCATE)' ) # Force checkpoint and truncate
118+ conn .execute ('PRAGMA wal_autocheckpoint = 500' ) # More frequent checkpoints for Docker
119+ conn .execute ('PRAGMA journal_size_limit = 67108864' ) # 64MB journal size limit
120+
121+ # Force checkpoint and truncate to clean up WAL file
122+ try :
123+ conn .execute ('PRAGMA wal_checkpoint(TRUNCATE)' )
124+ except Exception as checkpoint_error :
125+ logger .debug (f"WAL checkpoint failed (non-critical): { checkpoint_error } " )
96126
97- # Test the configuration worked
98- integrity_result = conn .execute ('PRAGMA integrity_check' ).fetchone ()
99- if integrity_result and integrity_result [0 ] != 'ok' :
100- logger .error (f"Database integrity check failed: { integrity_result } " )
101- raise sqlite3 .DatabaseError (f"Database integrity compromised: { integrity_result } " )
127+ # Test the configuration worked (skip integrity check for aggressive Synology mode)
128+ if not (is_synology and synology_opt_enabled ):
129+ integrity_result = conn .execute ('PRAGMA integrity_check' ).fetchone ()
130+ if integrity_result and integrity_result [0 ] != 'ok' :
131+ logger .error (f"Database integrity check failed: { integrity_result } " )
132+ raise sqlite3 .DatabaseError (f"Database integrity compromised: { integrity_result } " )
102133
103134 # Log optimization status for monitoring
104135 if is_synology :
136+ journal_mode = conn .execute ('PRAGMA journal_mode' ).fetchone ()[0 ]
105137 sync_mode = conn .execute ('PRAGMA synchronous' ).fetchone ()[0 ]
106138 cache_size = conn .execute ('PRAGMA cache_size' ).fetchone ()[0 ]
107139 mmap_size = conn .execute ('PRAGMA mmap_size' ).fetchone ()[0 ]
108- logger .info (f"Synology optimizations applied: sync={ sync_mode } , cache={ abs (cache_size / 1024 ):.1f} MB, mmap={ mmap_size / 1024 / 1024 :.0f} MB" )
140+ page_size = conn .execute ('PRAGMA page_size' ).fetchone ()[0 ]
141+ logger .info (f"Synology optimizations applied: journal={ journal_mode } , sync={ sync_mode } , "
142+ f"cache={ abs (cache_size / 1024 ):.1f} MB, mmap={ mmap_size / 1024 / 1024 :.0f} MB, page={ page_size } B" )
109143
110144 except Exception as e :
111145 logger .error (f"Error configuring database connection: { e } " )
0 commit comments