Files
ppf/mysqlite.py
Username e24f68500c style: normalize indentation and improve code style
- convert tabs to 4-space indentation
- add docstrings to modules and classes
- remove unused import (copy)
- use explicit object inheritance
- use 'while True' over 'while 1'
- use 'while args' over 'while len(args)'
- use '{}' over 'dict()'
- consistent string formatting
- Python 2/3 compatible Queue import
2025-12-20 23:18:45 +01:00

63 lines
2.2 KiB
Python

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""SQLite wrapper with retry logic and WAL mode."""
import time
import random
import sys
import sqlite3
class mysqlite(object):
"""SQLite connection wrapper with automatic retry on lock."""
def __init__(self, database, factory=None):
self.handle = sqlite3.connect(database)
if factory is not None:
self.handle.text_factory = factory
self.cursor = self.handle.cursor()
self.dbname = database
# Enable WAL mode for better concurrency
self.cursor.execute('PRAGMA journal_mode=WAL')
self.cursor.execute('PRAGMA synchronous=NORMAL')
def _try_op(self, op, query, args=None, rmin=1.5, rmax=7.0):
"""Execute operation with retry on database lock."""
while True:
try:
if query is None:
return op()
elif args is None:
return op(query)
else:
return op(query, args)
except sqlite3.OperationalError as e:
err_msg = str(e)
if 'database is locked' in err_msg:
sys.stderr.write('zzZzzZZ: db is locked (%s)\n' % self.dbname)
time.sleep(random.uniform(rmin, rmax))
continue
else:
sys.stderr.write('%s\nquery: %s\nargs: %s\n' % (
str(sys.exc_info()), str(query), str(args)))
raise
def execute(self, query, args=None, rmin=1.5, rmax=7.0):
"""Execute a single query with retry."""
return self._try_op(self.cursor.execute, query, args, rmin, rmax)
def executemany(self, query, args, rmin=1.5, rmax=7.0):
"""Execute query for multiple argument sets, batched."""
while args:
batch = args[:500]
self._try_op(self.cursor.executemany, query, batch, rmin, rmax)
args = args[500:]
def commit(self, rmin=1.5, rmax=7.0):
"""Commit transaction with retry."""
return self._try_op(self.handle.commit, None, None, rmin, rmax)
def close(self):
"""Close database connection."""
self.handle.close()