stargazer/db/mod.rs
1//! Database connection pool, schema migrations, and typed query modules.
2//!
3//! This module manages the `PostgreSQL` connection pool via sqlx and provides
4//! the schema migration entry point. Submodules contain typed query functions
5//! for each table:
6//!
7//! | Module | Table | Purpose |
8//! |---|---|---|
9//! | [`reflectors`] | `reflectors` | Registry of discovered D-STAR reflectors. |
10//! | [`activity`] | `activity_log` | Timestamped callsign observations. |
11//! | [`connected_nodes`] | `connected_nodes` | Live snapshot of linked nodes per reflector. |
12//! | [`streams`] | `streams` | Captured voice transmissions with audio. |
13//! | [`uploads`] | `streams` | Upload queue lifecycle management. |
14//!
15//! The pool is shared across all tiers via `sqlx::PgPool`, which is cheaply
16//! cloneable (it wraps an `Arc` internally).
17
18pub(crate) mod activity;
19pub(crate) mod connected_nodes;
20mod migrations;
21pub(crate) mod reflectors;
22pub(crate) mod streams;
23pub(crate) mod uploads;
24
25use crate::config::PostgresConfig;
26
27/// Creates and returns a `PostgreSQL` connection pool.
28///
29/// Connects to the database specified in `config.url` with the pool size
30/// limited to `config.max_connections`.
31///
32/// # Errors
33///
34/// Returns `sqlx::Error` if the database is unreachable or the connection
35/// string is malformed.
36pub(crate) async fn connect(config: &PostgresConfig) -> Result<sqlx::PgPool, sqlx::Error> {
37 let pool = sqlx::postgres::PgPoolOptions::new()
38 .max_connections(config.max_connections)
39 .connect(&config.url)
40 .await?;
41 Ok(pool)
42}
43
44/// Runs embedded database migrations.
45///
46/// Executes idempotent `CREATE TABLE IF NOT EXISTS` and `CREATE INDEX IF NOT
47/// EXISTS` statements to bring the schema up to date. Safe to call on every
48/// application startup.
49///
50/// # Errors
51///
52/// Returns `sqlx::Error` if any migration statement fails.
53pub(crate) async fn migrate(pool: &sqlx::PgPool) -> Result<(), sqlx::Error> {
54 migrations::run(pool).await
55}