From 9a1805e7796486c85b16912aa510a9e3631f90be Mon Sep 17 00:00:00 2001 From: Bulat Kurbanov Date: Fri, 16 Jan 2026 10:50:07 +0100 Subject: [PATCH] Run DB migrations at startup and add cached_files --- Cargo.toml | 2 +- ...260116094605_create_cached_files_table.sql | 54 +++++++++++++++++++ src/db.rs | 4 ++ src/main.rs | 12 ++++- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 migrations/20260116094605_create_cached_files_table.sql diff --git a/Cargo.toml b/Cargo.toml index e8b75b8..c38b887 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,4 +54,4 @@ teloxide = { version = "0.17.0", features = ["macros", "webhooks-axum", "cache-m moka = { version = "0.12.10", features = ["future"] } -sqlx = { version = "0.8.3", features = ["runtime-tokio", "postgres", "macros"] } +sqlx = { version = "0.8.3", features = ["runtime-tokio", "postgres", "macros", "migrate"] } diff --git a/migrations/20260116094605_create_cached_files_table.sql b/migrations/20260116094605_create_cached_files_table.sql new file mode 100644 index 0000000..b98593b --- /dev/null +++ b/migrations/20260116094605_create_cached_files_table.sql @@ -0,0 +1,54 @@ +-- Create cached_files table with all indexes and constraints +-- This migration is idempotent and safe to run on existing databases + +-- Create table if not exists +CREATE TABLE IF NOT EXISTS cached_files ( + id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('cached_files_id_seq'::regclass), + object_id INTEGER NOT NULL, + object_type VARCHAR(8) NOT NULL, + message_id BIGINT NOT NULL, + chat_id BIGINT NOT NULL +); + +-- Create sequence if not exists (for compatibility) +CREATE SEQUENCE IF NOT EXISTS cached_files_id_seq; + +-- Ensure the sequence is owned by the table column +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_depend + WHERE refobjid = 'cached_files'::regclass + AND objid = 'cached_files_id_seq'::regclass + ) THEN + ALTER SEQUENCE cached_files_id_seq OWNED BY cached_files.id; + END IF; +END $$; + +-- Create indexes if they don't exist +CREATE UNIQUE INDEX IF NOT EXISTS ix_cached_files_message_id ON cached_files (message_id); +CREATE INDEX IF NOT EXISTS ix_cached_files_object_id ON cached_files (object_id); +CREATE INDEX IF NOT EXISTS ix_cached_files_object_type ON cached_files (object_type); + +-- Create unique constraints if they don't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'uc_cached_files_message_id_chat_id' + ) THEN + ALTER TABLE cached_files + ADD CONSTRAINT uc_cached_files_message_id_chat_id UNIQUE (message_id, chat_id); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'uc_cached_files_object_id_object_type' + ) THEN + ALTER TABLE cached_files + ADD CONSTRAINT uc_cached_files_object_id_object_type UNIQUE (object_id, object_type); + END IF; +END $$; diff --git a/src/db.rs b/src/db.rs index 6bc8831..6dfabc0 100644 --- a/src/db.rs +++ b/src/db.rs @@ -19,3 +19,7 @@ pub async fn get_pg_pool() -> PgPool { .await .unwrap() } + +pub async fn run_migrations(pool: &PgPool) -> Result<(), sqlx::migrate::MigrateError> { + sqlx::migrate!("./migrations").run(pool).await +} diff --git a/src/main.rs b/src/main.rs index d499584..2ae6b50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use std::{net::SocketAddr, str::FromStr}; use tracing::info; use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt}; -use crate::views::get_router; +use crate::{db::run_migrations, views::get_router}; #[tokio::main] async fn main() { @@ -40,6 +40,16 @@ async fn main() { let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); + // Get database pool + let pool = db::get_pg_pool().await; + + // Run migrations + info!("Running database migrations..."); + run_migrations(&pool) + .await + .expect("Failed to run database migrations"); + info!("Database migrations completed successfully"); + let app = get_router().await; info!("Start webserver...");