From 95b8b0277bd34a850ea765bcb4621f69a3b47069 Mon Sep 17 00:00:00 2001 From: Jo Date: Tue, 7 Jul 2026 12:13:07 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20SQLite=20database=20locked=20=E2=80=94?= =?UTF-8?q?=20timeout=3D10=20on=20get=5Fdb,=20direct=20connect=20in=20HA?= =?UTF-8?q?=20sync=20thread?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/app.py b/app.py index d21afb1..37942da 100644 --- a/app.py +++ b/app.py @@ -75,7 +75,7 @@ def require_login_global(): return redirect(url_for('login')) def get_db(): - conn = sqlite3.connect(DATABASE) + conn = sqlite3.connect(DATABASE, timeout=10) conn.row_factory = sqlite3.Row return conn @@ -1973,7 +1973,14 @@ def _ha_fetch_all_states(ha_url, ha_token): def _ha_sync_once(): """Poll HA et met a jour les print_slots actifs.""" try: - s = get_settings() + # Use direct connection with timeout — avoids locking conflicts with Flask request threads + _conn = sqlite3.connect(DATABASE, timeout=15) + _conn.row_factory = sqlite3.Row + try: + _s = _conn.execute("SELECT key, value FROM settings").fetchall() + finally: + _conn.close() + s = {r['key']: r['value'] for r in _s} ha_url = str(s.get('ha_url', '')).rstrip('/') ha_token = str(s.get('ha_token', '')) if not ha_url or not ha_token: @@ -1981,7 +1988,8 @@ def _ha_sync_once(): states = _ha_fetch_all_states(ha_url, ha_token) if not states: return - conn = get_db() + conn = sqlite3.connect(DATABASE, timeout=15) + conn.row_factory = sqlite3.Row printers = conn.execute( "SELECT id, name, ha_entity_prefix FROM printers " "WHERE ha_entity_prefix IS NOT NULL AND ha_entity_prefix != ''" @@ -2014,8 +2022,10 @@ def _ha_sync_once(): if ha_ignored > 0: conn.execute('UPDATE print_slots SET pieces_ignored=? WHERE id=?', (ha_ignored, slot['id'])) - conn.commit() - conn.close() + try: + conn.commit() + finally: + conn.close() except Exception as e: print(f'[HA sync] {e}')