new comments

This commit is contained in:
erik 2025-05-24 18:33:03 +00:00
parent b2f649a489
commit 09404da121
13 changed files with 430 additions and 70 deletions

44
db.py
View file

@ -1,12 +1,20 @@
"""SQLite3 helper module for local telemetry storage.
Provides functions to initialize the local database schema and save
telemetry snapshots into history and live_state tables.
Enforces WAL mode, size limits, and auto-vacuum for efficient storage.
"""
import os
import sqlite3
from typing import Dict
from datetime import datetime, timedelta
# Local SQLite database file name (used when running without TimescaleDB)
DB_FILE = "dereth.db"
# Maximum allowed database size (in MB). Defaults to 2048 (2GB). Override via env DB_MAX_SIZE_MB.
MAX_DB_SIZE_MB = int(os.getenv("DB_MAX_SIZE_MB", "2048"))
# Retention window for telemetry history in days. Override via env DB_RETENTION_DAYS.
# Retention window for telemetry history in days (currently not auto-enforced).
# Override via env DB_RETENTION_DAYS for future cleanup scripts.
MAX_RETENTION_DAYS = int(os.getenv("DB_RETENTION_DAYS", "7"))
# SQLite runtime limits customization
DB_MAX_SQL_LENGTH = int(os.getenv("DB_MAX_SQL_LENGTH", "1000000000"))
@ -16,8 +24,15 @@ DB_WAL_AUTOCHECKPOINT_PAGES = int(os.getenv("DB_WAL_AUTOCHECKPOINT_PAGES", "1000
def init_db() -> None:
"""Create tables if they do not exist (extended with kills_per_hour and onlinetime)."""
"""
Initialize local SQLite database schema for telemetry logging.
- Applies SQLite PRAGMA settings for performance and file size management
- Ensures WAL journaling and auto-vacuum for concurrency and compaction
- Creates telemetry_log for full history and live_state for latest snapshot per character
"""
# Open connection with a longer timeout
# Open connection with extended timeout for schema operations
conn = sqlite3.connect(DB_FILE, timeout=30)
# Bump SQLite runtime limits
conn.setlimit(sqlite3.SQLITE_LIMIT_LENGTH, DB_MAX_SQL_LENGTH)
@ -25,16 +40,20 @@ def init_db() -> None:
conn.setlimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, DB_MAX_SQL_VARIABLES)
c = conn.cursor()
# Enable auto_vacuum FULL and rebuild DB so that deletions shrink the file
# Enable full auto-vacuum to shrink database file on deletes
c.execute("PRAGMA auto_vacuum=FULL;")
conn.commit()
# Rebuild database to apply auto_vacuum changes
c.execute("VACUUM;")
conn.commit()
# Switch to WAL mode for concurrency, adjust checkpointing, and enforce max size
# Configure write-ahead logging for concurrency and performance
c.execute("PRAGMA journal_mode=WAL")
c.execute("PRAGMA synchronous=NORMAL")
# Auto-checkpoint after specified WAL frames to limit WAL file size
c.execute(f"PRAGMA wal_autocheckpoint={DB_WAL_AUTOCHECKPOINT_PAGES}")
# History log
# Create history log table for all telemetry snapshots
c.execute(
"""
CREATE TABLE IF NOT EXISTS telemetry_log (
@ -57,7 +76,7 @@ def init_db() -> None:
"""
)
# Live snapshot (upsert)
# Create live_state table for upserts of the most recent snapshot per character
c.execute(
"""
CREATE TABLE IF NOT EXISTS live_state (
@ -84,20 +103,27 @@ def init_db() -> None:
def save_snapshot(data: Dict) -> None:
"""Insert snapshot into history and upsert into live_state (with new fields)."""
# Open connection with a longer busy timeout
"""
Save a telemetry snapshot into the local SQLite database.
Inserts a full record into telemetry_log (history) and upserts into live_state
for quick lookup of the most recent data per character.
Respects WAL mode and checkpoint settings on each connection.
"""
# Open new connection with extended timeout for inserting data
conn = sqlite3.connect(DB_FILE, timeout=30)
# Bump SQLite runtime limits on this connection
conn.setlimit(sqlite3.SQLITE_LIMIT_LENGTH, DB_MAX_SQL_LENGTH)
conn.setlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH, DB_MAX_SQL_LENGTH)
conn.setlimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, DB_MAX_SQL_VARIABLES)
c = conn.cursor()
# Ensure WAL mode, checkpointing, and size limit on this connection
# Ensure WAL mode and checkpointing settings on this connection
c.execute("PRAGMA journal_mode=WAL")
c.execute("PRAGMA synchronous=NORMAL")
c.execute(f"PRAGMA wal_autocheckpoint={DB_WAL_AUTOCHECKPOINT_PAGES}")
# Insert full history row
# Insert the snapshot into the telemetry_log (history) table
c.execute(
"""
INSERT INTO telemetry_log (
@ -125,7 +151,7 @@ def save_snapshot(data: Dict) -> None:
),
)
# Upsert into live_state
# Upsert (insert or update) the latest snapshot into live_state table
c.execute(
"""
INSERT INTO live_state (