Johan review

This commit is contained in:
erik 2025-05-25 22:12:08 +00:00
parent d9b3b403da
commit 7845570819
3 changed files with 53 additions and 31 deletions

View file

@ -7,6 +7,7 @@ import os
import sqlalchemy
from databases import Database
from sqlalchemy import MetaData, Table, Column, Integer, String, Float, DateTime, text
from sqlalchemy import Index
# Environment: Postgres/TimescaleDB connection URL
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:password@localhost:5432/dereth")
@ -43,6 +44,12 @@ telemetry_events = Table(
Column("mem_handles", Integer, nullable=True),
Column("latency_ms", Float, nullable=True),
)
# Composite index to accelerate Grafana queries filtering by character_name then ordering by timestamp
Index(
'ix_telemetry_events_char_ts',
telemetry_events.c.character_name,
telemetry_events.c.timestamp
)
# Table for persistent total kills per character
char_stats = Table(
@ -108,26 +115,41 @@ async def init_db_async():
engine = sqlalchemy.create_engine(DATABASE_URL)
# Reflects metadata definitions into actual database tables via SQLAlchemy
metadata.create_all(engine)
# Enable TimescaleDB extension and convert telemetry_events to hypertable
# Use a transactional context to ensure DDL statements are committed
with engine.begin() as conn:
# Enable or update TimescaleDB extension
# Install or confirm TimescaleDB extension to support hypertables
try:
conn.execute(text("CREATE EXTENSION IF NOT EXISTS timescaledb"))
except Exception as e:
print(f"Warning: failed to create extension timescaledb: {e}")
# Update TimescaleDB extension if an older version exists
try:
conn.execute(text("ALTER EXTENSION timescaledb UPDATE"))
except Exception as e:
print(f"Warning: failed to update timescaledb extension: {e}")
# Create hypertable for telemetry_events, skip default indexes to avoid collisions
# Transform telemetry_events into a hypertable partitioned by timestamp
try:
# Ensure TimescaleDB extension is installed and telemetry_events is a hypertable
# Run DDL in autocommit mode so errors don't abort subsequent statements
try:
with engine.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
# Install extension if missing
try:
conn.execute(text("CREATE EXTENSION IF NOT EXISTS timescaledb"))
except Exception as e:
print(f"Warning: failed to create extension timescaledb: {e}")
# Convert to hypertable, migrating existing data and skipping default index creation
try:
conn.execute(text(
"SELECT create_hypertable('telemetry_events', 'timestamp', "
"if_not_exists => true, migrate_data => true, create_default_indexes => false)"
))
except Exception as e:
print(f"Warning: failed to create hypertable telemetry_events: {e}")
except Exception as e:
print(f"Warning: timescale extension/hypertable setup failed: {e}")
# Ensure composite index exists for efficient time-series queries by character
try:
with engine.connect() as conn:
conn.execute(text(
"SELECT create_hypertable('telemetry_events', 'timestamp', \
if_not_exists => true, create_default_indexes => false)"
"CREATE INDEX IF NOT EXISTS ix_telemetry_events_char_ts "
"ON telemetry_events (character_name, timestamp)"
))
except Exception as e:
print(f"Warning: failed to create hypertable telemetry_events: {e}")
except Exception as e:
print(f"Warning: failed to create composite index ix_telemetry_events_char_ts: {e}")
# Disable parallel workers at the system level to avoid OOMs from large parallel scans
try:
# Apply settings outside transaction for ALTER SYSTEM
conn2 = engine.connect().execution_options(isolation_level="AUTOCOMMIT")
conn2.execute(text("ALTER SYSTEM SET max_parallel_workers_per_gather = 0"))
conn2.execute(text("ALTER SYSTEM SET max_parallel_workers = 0"))
conn2.execute(text("SELECT pg_reload_conf()"))
conn2.close()
except Exception as e:
print(f"Warning: failed to disable parallel workers: {e}")