auto back up upon save

This commit is contained in:
edo-neo 2025-09-15 11:23:58 +02:00
parent e537721aca
commit 9acbb9530a

View File

@ -1,4 +1,6 @@
from peewee import TextField
import time
import logging
from peewee import TextField, OperationalError
from playhouse.shortcuts import model_to_dict
from . import db, models_reference
@ -18,6 +20,33 @@ class Crud_DB:
for column_name, filter in filters.items():
self.filter(column_name, filter, filter_storage=self.default_filters)
def _execute_with_retry(self, func, max_retries=8, base_delay=0.1):
"""Execute a DB operation with retry on transient SQLite 'database is locked' errors."""
last_exc = None
for attempt in range(max_retries):
try:
return func()
except OperationalError as e:
msg = str(e).lower()
if "database is locked" in msg or "database is busy" in msg:
delay = min(base_delay * (2 ** attempt), 1.5)
try:
logging.getLogger(__name__).warning(
f"SQLite busy/locked, retrying commit (attempt {attempt + 1}/{max_retries}) after {delay:.2f}s"
)
except Exception:
pass
time.sleep(delay)
last_exc = e
continue
# Not a transient lock error: re-raise immediately
raise
# Exhausted retries
if last_exc is not None:
raise last_exc
# Fallback if no exception captured (should not happen)
return func()
@db.connection_context()
@db.atomic()
def commit(self, data, deleted_rows=None):
@ -25,7 +54,7 @@ class Crud_DB:
if hasattr(self.table_model, "crud_delete"):
deleted = self.table_model.crud_delete(deleted_rows)
else:
deleted = self.table_model.delete().where(self.table_pk << deleted_rows).execute()
deleted = self._execute_with_retry(lambda: self.table_model.delete().where(self.table_pk << deleted_rows).execute())
if deleted != len(deleted_rows):
raise AssertionError(f"deleted {deleted} rows instead of the expected {len(deleted_rows)}")
# SQLITE DOES NOT SUPPORT UPDATE, ONLY REPLACE
@ -42,7 +71,7 @@ class Crud_DB:
if hasattr(self.table_model, "crud_update"):
self.table_model.crud_update(complete_data)
else:
self.table_model.insert_many(complete_data).on_conflict_replace().execute()
self._execute_with_retry(lambda: self.table_model.insert_many(complete_data).on_conflict_replace().execute())
def revert(self):
self.sorting.clear()