auto back up upon save
This commit is contained in:
parent
e537721aca
commit
9acbb9530a
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user