update
This commit is contained in:
@@ -122,50 +122,108 @@ uSpot_profile_id = 1
|
||||
conn = sqlite3.connect("/var/www/moduleair_pro_4g/sqlite/sensors.db")
|
||||
cursor = conn.cursor()
|
||||
|
||||
def update_config_sqlite(key, value, value_type=None):
|
||||
def update_config_sqlite(key, value, value_type=None, max_retries=4, retry_delay=1.0):
|
||||
"""
|
||||
Update or insert a configuration value in SQLite config table
|
||||
Update or insert a configuration value in SQLite config table with retry logic
|
||||
|
||||
Args:
|
||||
key (str): Configuration key
|
||||
value: Configuration value (any type)
|
||||
value_type (str, optional): Force specific type ('str', 'int', 'float', 'bool')
|
||||
If None, auto-detect from value type
|
||||
max_retries (int): Maximum number of retry attempts (default: 4)
|
||||
retry_delay (float): Delay between retries in seconds (default: 1.0)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Auto-detect type if not specified
|
||||
if value_type is None:
|
||||
if isinstance(value, bool):
|
||||
value_type = 'bool'
|
||||
elif isinstance(value, int):
|
||||
value_type = 'int'
|
||||
elif isinstance(value, float):
|
||||
value_type = 'float'
|
||||
else:
|
||||
value_type = 'str'
|
||||
|
||||
# Convert value to string for storage
|
||||
if value_type == 'bool':
|
||||
str_value = '1' if value else '0'
|
||||
|
||||
# Auto-detect type if not specified
|
||||
if value_type is None:
|
||||
if isinstance(value, bool):
|
||||
value_type = 'bool'
|
||||
elif isinstance(value, int):
|
||||
value_type = 'int'
|
||||
elif isinstance(value, float):
|
||||
value_type = 'float'
|
||||
else:
|
||||
str_value = str(value)
|
||||
|
||||
# Use INSERT OR REPLACE to update existing or create new
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO config_table (key, value, type)
|
||||
VALUES (?, ?, ?)
|
||||
""", (key, str_value, value_type))
|
||||
|
||||
conn.commit()
|
||||
print(f"✓ Config updated: {key} = {value} ({value_type})")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error updating config {key}: {e}")
|
||||
return False
|
||||
value_type = 'str'
|
||||
|
||||
# Convert value to string for storage
|
||||
if value_type == 'bool':
|
||||
str_value = '1' if value else '0'
|
||||
else:
|
||||
str_value = str(value)
|
||||
|
||||
# Retry logic
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
# Use WAL mode and immediate transaction for better concurrency
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA busy_timeout=30000") # Wait up to 30 seconds for lock
|
||||
|
||||
# Begin immediate transaction to acquire lock quickly
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
|
||||
# Use INSERT OR REPLACE to update existing or create new
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO config_table (key, value, type)
|
||||
VALUES (?, ?, ?)
|
||||
""", (key, str_value, value_type))
|
||||
|
||||
conn.commit()
|
||||
print(f"✓ Config updated: {key} = {value} ({value_type}) [attempt {attempt + 1}]")
|
||||
return True
|
||||
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e).lower() or "locked" in str(e).lower():
|
||||
print(f"⚠ Database locked on attempt {attempt + 1}/{max_retries} for key '{key}': {e}")
|
||||
|
||||
# Rollback any pending transaction
|
||||
try:
|
||||
conn.rollback()
|
||||
except:
|
||||
pass
|
||||
|
||||
# If not the last attempt, wait and retry
|
||||
if attempt < max_retries - 1:
|
||||
print(f"⏳ Retrying in {retry_delay} seconds...")
|
||||
time.sleep(retry_delay)
|
||||
# Increase delay slightly for each retry (exponential backoff)
|
||||
retry_delay *= 1.2
|
||||
else:
|
||||
print(f"✗ Failed to update config {key} after {max_retries} attempts: database remains locked")
|
||||
return False
|
||||
else:
|
||||
# Non-lock related operational error
|
||||
print(f"✗ Operational error updating config {key}: {e}")
|
||||
try:
|
||||
conn.rollback()
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
# Other unexpected errors
|
||||
print(f"✗ Unexpected error updating config {key} on attempt {attempt + 1}: {e}")
|
||||
try:
|
||||
conn.rollback()
|
||||
except:
|
||||
pass
|
||||
|
||||
# For unexpected errors, don't retry unless it's clearly a temporary issue
|
||||
if "busy" in str(e).lower() or "locked" in str(e).lower():
|
||||
if attempt < max_retries - 1:
|
||||
print(f"⏳ Retrying in {retry_delay} seconds...")
|
||||
time.sleep(retry_delay)
|
||||
retry_delay *= 1.2
|
||||
continue
|
||||
|
||||
return False
|
||||
|
||||
# If we get here, all retries failed
|
||||
print(f"✗ Failed to update config {key} after {max_retries} attempts")
|
||||
return False
|
||||
|
||||
#get config data from SQLite table
|
||||
def load_config_sqlite():
|
||||
|
||||
Reference in New Issue
Block a user