MosswartOverlord/ARCHITECTURE.md
2025-05-25 22:12:08 +00:00

95 lines
No EOL
5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 on `telemetry_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.
- **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_URL` controls the connection string.
### Tables and Hypertable
1. **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)`.
2. **char_stats**
- Tracks cumulative kills per character.
- Columns: `character_name` (PK), `total_kills` (Integer).
3. **rare_stats**
- Tracks total rare spawns per character.
- Columns: `character_name` (PK), `total_rares` (Integer).
4. **rare_stats_sessions**
- Tracks rarities per session.
- Columns: composite PK `(character_name, session_id)`, `session_rares` (Integer).
5. **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.
6. **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:
1. Creates all tables via SQLAlchemys `metadata.create_all()`.
2. Enables TimescaleDB extension.
3. Converts `telemetry_events` to a hypertable, skipping default index creation to avoid PK/index collisions.
- Alembic is configured for schema migrations (`alembic/` directory).
## Data Ingestion Flow
1. **Plugin** connects to `/ws/position` with a shared secret.
2. Sends JSON frames of types:
- `telemetry`: parsed into `TelemetrySnapshot`, upserted into `live_snapshots`, persisted to `telemetry_events`, and broadcast to browser clients.
- `spawn`: parsed into `SpawnEvent`, inserted into `spawn_events`.
- `rare`: increments `rare_stats` and `rare_stats_sessions` via upsert operations.
- `chat`: broadcast to browser clients without DB writes.
3. **Browser** connects to `/ws/live` to 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.