Skip to content

Commit de59156

Browse files
committed
Fix GitHub issue #629: Windows executable database access failure after reboot - Enhanced database path resolution for Windows with AppData support and WAL mode fallback
1 parent 521a5e6 commit de59156

File tree

1 file changed

+80
-18
lines changed

1 file changed

+80
-18
lines changed

src/primary/utils/database.py

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,36 @@ def execute_query(self, query: str, params: tuple = None) -> List[tuple]:
3333
return cursor.fetchall()
3434

3535
def _configure_connection(self, conn):
36-
"""Configure SQLite connection with Synology NAS compatible settings"""
37-
conn.execute('PRAGMA foreign_keys = ON')
38-
conn.execute('PRAGMA journal_mode = WAL')
39-
conn.execute('PRAGMA synchronous = NORMAL')
40-
conn.execute('PRAGMA cache_size = 10000')
41-
conn.execute('PRAGMA temp_store = MEMORY')
42-
conn.execute('PRAGMA mmap_size = 268435456')
43-
conn.execute('PRAGMA wal_autocheckpoint = 1000')
44-
conn.execute('PRAGMA busy_timeout = 30000')
36+
"""Configure SQLite connection with cross-platform compatible settings"""
37+
try:
38+
conn.execute('PRAGMA foreign_keys = ON')
39+
40+
# Try WAL mode first, fall back to DELETE mode on Windows if it fails
41+
try:
42+
conn.execute('PRAGMA journal_mode = WAL')
43+
except Exception as wal_error:
44+
logger.warning(f"WAL mode failed, using DELETE mode: {wal_error}")
45+
conn.execute('PRAGMA journal_mode = DELETE')
46+
47+
conn.execute('PRAGMA synchronous = NORMAL')
48+
conn.execute('PRAGMA cache_size = 10000')
49+
conn.execute('PRAGMA temp_store = MEMORY')
50+
51+
# Skip mmap on Windows if it causes issues
52+
import platform
53+
if platform.system() != "Windows":
54+
conn.execute('PRAGMA mmap_size = 268435456')
55+
56+
# Only set WAL checkpoint if we're using WAL mode
57+
result = conn.execute('PRAGMA journal_mode').fetchone()
58+
if result and result[0] == 'wal':
59+
conn.execute('PRAGMA wal_autocheckpoint = 1000')
60+
61+
conn.execute('PRAGMA busy_timeout = 30000')
62+
except Exception as e:
63+
logger.error(f"Error configuring database connection: {e}")
64+
# Continue with basic connection if configuration fails
65+
pass
4566

4667
def get_connection(self):
4768
"""Get a configured SQLite connection with Synology NAS compatibility"""
@@ -50,23 +71,64 @@ def get_connection(self):
5071
return conn
5172

5273
def _get_database_path(self) -> Path:
53-
"""Get database path - use /config for Docker, local data directory for development"""
74+
"""Get database path - use /config for Docker, Windows AppData, or local data directory"""
5475
# Check if running in Docker (config directory exists)
5576
config_dir = Path("/config")
5677
if config_dir.exists() and config_dir.is_dir():
5778
# Running in Docker - use persistent config directory
5879
return config_dir / "huntarr.db"
59-
else:
60-
# For local development, use data directory in project root
61-
project_root = Path(__file__).parent.parent.parent.parent
62-
data_dir = project_root / "data"
63-
64-
# Ensure directory exists
65-
data_dir.mkdir(parents=True, exist_ok=True)
66-
return data_dir / "huntarr.db"
80+
81+
# Check if we have a Windows-specific config directory set
82+
windows_config = os.environ.get("HUNTARR_CONFIG_DIR")
83+
if windows_config:
84+
config_path = Path(windows_config)
85+
config_path.mkdir(parents=True, exist_ok=True)
86+
return config_path / "huntarr.db"
87+
88+
# Check if we're on Windows and use AppData
89+
import platform
90+
if platform.system() == "Windows":
91+
appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
92+
windows_config_dir = Path(appdata) / "Huntarr"
93+
windows_config_dir.mkdir(parents=True, exist_ok=True)
94+
return windows_config_dir / "huntarr.db"
95+
96+
# For local development on non-Windows, use data directory in project root
97+
project_root = Path(__file__).parent.parent.parent.parent
98+
data_dir = project_root / "data"
99+
100+
# Ensure directory exists
101+
data_dir.mkdir(parents=True, exist_ok=True)
102+
return data_dir / "huntarr.db"
67103

68104
def ensure_database_exists(self):
69105
"""Create database and all tables if they don't exist"""
106+
try:
107+
# Ensure the database directory exists and is writable
108+
db_dir = self.db_path.parent
109+
db_dir.mkdir(parents=True, exist_ok=True)
110+
111+
# Test write permissions
112+
test_file = db_dir / f"db_test_{int(time.time())}.tmp"
113+
try:
114+
test_file.write_text("test")
115+
test_file.unlink()
116+
except Exception as perm_error:
117+
logger.error(f"Database directory not writable: {db_dir} - {perm_error}")
118+
# On Windows, try an alternative location
119+
import platform
120+
if platform.system() == "Windows":
121+
alt_dir = Path(os.path.expanduser("~")) / "Documents" / "Huntarr"
122+
alt_dir.mkdir(parents=True, exist_ok=True)
123+
self.db_path = alt_dir / "huntarr.db"
124+
logger.info(f"Using alternative database location: {self.db_path}")
125+
else:
126+
raise perm_error
127+
128+
except Exception as e:
129+
logger.error(f"Error setting up database directory: {e}")
130+
raise
131+
70132
with self.get_connection() as conn:
71133

72134
# Create app_configs table for all app settings

0 commit comments

Comments
 (0)