5 KiB
5 KiB
Project Architecture and Data Model
This document provides an overview of the project files, their roles, and a detailed description of the database architecture and data model.
Project Structure
Root directory:
- Dockerfile: Defines the Python 3.12-slim image, installs dependencies (FastAPI, Uvicorn, SQLAlchemy, databases, TimescaleDB support), and runs the app.
- docker-compose.yml: Orchestrates two services:
- dereth-tracker: The FastAPI application container.
- db: A TimescaleDB (PostgreSQL 14 + TimescaleDB extension) container for persistent storage.
- README.md: High-level documentation and usage instructions.
- EVENT_FORMATS.json: Example JSON payloads for all event types (
telemetry,spawn,chat,rare). - db.py: Legacy SQLite-based storage (telemetry_log & live_state tables, WAL mode, auto-vacuum).
- db_async.py: Async database definitions for PostgreSQL/TimescaleDB:
- Table schemas (SQLAlchemy Core):
telemetry_events,char_stats,rare_stats,rare_stats_sessions,spawn_events,rare_events.
init_db_async(): Creates tables, enables TimescaleDB extension, and configures a hypertable ontelemetry_events.- main.py: The FastAPI application:
- HTTP endpoints:
/debug,/live,/history,/trails. - WebSocket endpoints:
/ws/position(plugin data in),/ws/live(browser live updates). - Pydantic models:
TelemetrySnapshot,SpawnEvent. - In-memory state:
live_snapshots, WebSocket connection registries.
- HTTP endpoints:
- generate_data.py: Sample WebSocket client that sends synthetic telemetry snapshots.
- alembic/ & alembic.ini: Migration tooling for evolving the database schema.
- static/: Frontend assets (HTML, CSS, JavaScript, images) for the live map UI.
- FIXES.md, LESSONSLEARNED.md, TODO.md: Project notes and future work.
Database Overview
Technology Stack
- PostgreSQL 14 with TimescaleDB extension for time-series optimization.
- databases library (async) with SQLAlchemy Core for schema definitions and queries.
- Environment variable:
DATABASE_URLcontrols the connection string.
Tables and Hypertable
-
telemetry_events (hypertable)
- Columns:
id: Integer, primary key.character_name(String),char_tag(String, nullable),session_id(String, indexed).timestamp(DateTime with TZ, indexed) — partitioning column for the hypertable.ew,ns,z: Float coordinates.kills,deaths,rares_found,prismatic_taper_count: Integer metrics.kills_per_hour,onlinetime(String),vt_state(String).- Optional:
mem_mb,cpu_pct,mem_handles,latency_ms.
- Created via
SELECT create_hypertable('telemetry_events', 'timestamp', if_not_exists=>true, create_default_indexes=>false).
- Columns:
-
char_stats
- Tracks cumulative kills per character.
- Columns:
character_name(PK),total_kills(Integer).
-
rare_stats
- Tracks total rare spawns per character.
- Columns:
character_name(PK),total_rares(Integer).
-
rare_stats_sessions
- Tracks rarities per session.
- Columns: composite PK
(character_name, session_id),session_rares(Integer).
-
spawn_events
- Records individual mob spawn events for heatmapping.
- Columns:
id(PK),character_name(String),mob(String),timestamp(DateTime),ew,ns,z(Float). - Coordinates (
ew,ns,z) can be sent as JSON numbers or strings and are coerced to floats.
-
rare_events
- Records each rare spawn event for future heatmaps and analysis.
- Columns:
id(PK),character_name(String),name(String),timestamp(DateTime),ew,ns,z(Float).
Initialization and Migrations
- On startup (
main.py),init_db_async()is called:- Creates all tables via SQLAlchemy’s
metadata.create_all(). - Enables TimescaleDB extension.
- Converts
telemetry_eventsto a hypertable, skipping default index creation to avoid PK/index collisions.
- Creates all tables via SQLAlchemy’s
- Alembic is configured for schema migrations (
alembic/directory).
Data Ingestion Flow
- Plugin connects to
/ws/positionwith a shared secret. - Sends JSON frames of types:
telemetry: parsed intoTelemetrySnapshot, upserted intolive_snapshots, persisted totelemetry_events, and broadcast to browser clients.spawn: parsed intoSpawnEvent, inserted intospawn_events.rare: incrementsrare_statsandrare_stats_sessionsvia upsert operations.chat: broadcast to browser clients without DB writes.
- Browser connects to
/ws/liveto receive live updates and can send commands to plugins.
HTTP Query Endpoints
- GET /live: returns recent snapshots (last 30s) plus rare counts per character.
- GET /history: returns ordered telemetry history with optional time filters.
- GET /trails: returns positional trails for a lookback window.
This architecture enables real-time telemetry ingestion, historical time-series analysis, and an interactive front-end map for tracking players and spawn events.