fix: HA sync uses per-printer autocommit connections to prevent database locked
Deploy via Portainer / deploy (push) Successful in 1s

This commit is contained in:
Jo
2026-07-07 13:38:59 +02:00
parent 522a0c5e83
commit f51a78940f
+34 -31
View File
@@ -2040,46 +2040,49 @@ def _ha_sync_once():
states = _ha_fetch_all_states(ha_url, ha_token) states = _ha_fetch_all_states(ha_url, ha_token)
if not states: if not states:
return return
# Ouvrir la connexion d'écriture APRÈS l'appel HTTP (qui peut être long) # Lire les imprimantes avec une connexion courte (lecture seule)
conn = sqlite3.connect(DATABASE, timeout=30) _rc = sqlite3.connect(DATABASE, timeout=15)
conn.row_factory = sqlite3.Row _rc.row_factory = sqlite3.Row
conn.execute('PRAGMA journal_mode=WAL') printers = _rc.execute(
printers = conn.execute(
"SELECT id, name, ha_entity_prefix FROM printers " "SELECT id, name, ha_entity_prefix FROM printers "
"WHERE ha_entity_prefix IS NOT NULL AND ha_entity_prefix != ''" "WHERE ha_entity_prefix IS NOT NULL AND ha_entity_prefix != ''"
).fetchall() ).fetchall()
_rc.close()
now_iso = datetime.now(timezone.utc).replace(tzinfo=None).isoformat() now_iso = datetime.now(timezone.utc).replace(tzinfo=None).isoformat()
window = (datetime.now(timezone.utc).replace(tzinfo=None) + timedelta(minutes=30)).isoformat() window = (datetime.now(timezone.utc).replace(tzinfo=None) + timedelta(minutes=30)).isoformat()
for p in printers: for p in printers:
prefix = p['ha_entity_prefix'] prefix = p['ha_entity_prefix']
ha_status = states.get(f'sensor.{prefix}_etat_de_l_impression', 'unknown') ha_status = states.get(f'sensor.{prefix}_etat_de_l_impression', 'unknown')
ha_error = states.get(f'binary_sensor.{prefix}_erreur_d_impression', 'off') ha_error = states.get(f'binary_sensor.{prefix}_erreur_d_impression', 'off')
slot = conn.execute( # Connexion courte par imprimante : on lit, on écrit, on commit, on ferme
"SELECT id, status FROM print_slots " wc = sqlite3.connect(DATABASE, timeout=15, isolation_level=None)
"WHERE printer_id=? AND status IN ('planned','running') " wc.row_factory = sqlite3.Row
"AND planned_start <= ? AND planned_end >= ? " try:
"ORDER BY planned_start DESC LIMIT 1", slot = wc.execute(
(p['id'], window, now_iso) "SELECT id, status FROM print_slots "
).fetchone() "WHERE printer_id=? AND status IN ('planned','running') "
if not slot: "AND planned_start <= ? AND planned_end >= ? "
continue "ORDER BY planned_start DESC LIMIT 1",
new_status = None (p['id'], window, now_iso)
if ha_error == 'on': ).fetchone()
new_status = 'failed' if not slot:
elif ha_status == 'finish': continue
new_status = 'done' new_status = None
elif ha_status == 'running' and slot['status'] == 'planned': if ha_error == 'on':
new_status = 'running' new_status = 'failed'
if new_status: elif ha_status == 'finish':
conn.execute('UPDATE print_slots SET status=? WHERE id=?', new_status = 'done'
(new_status, slot['id'])) elif ha_status == 'running' and slot['status'] == 'planned':
if ha_ignored > 0: new_status = 'running'
conn.execute('UPDATE print_slots SET pieces_ignored=? WHERE id=?', if new_status:
(ha_ignored, slot['id'])) wc.execute('UPDATE print_slots SET status=? WHERE id=?',
try: (new_status, slot['id']))
conn.commit() if ha_ignored > 0:
finally: wc.execute('UPDATE print_slots SET pieces_ignored=? WHERE id=?',
conn.close() (ha_ignored, slot['id']))
finally:
wc.close()
except Exception as e: except Exception as e:
print(f'[HA sync] {e}') print(f'[HA sync] {e}')