This commit is contained in:
Kirill
2026-07-02 23:13:13 +07:00
parent e997a20fe6
commit d4a57c0b6a
34 changed files with 524 additions and 67 deletions
+26 -4
View File
@@ -1,3 +1,9 @@
//! Точка входа. Поднимает Postgres-пул, собирает `ApiState` (репозиторий + сервисы),
//! и параллельно запускает три задачи до сигнала остановки: HTTP API (axum),
//! Telegram-бот (teloxide) и фоновый воркер биллинга (`tasks::run_background_tasks`).
//! Флаг `--migrate` переводит процесс в одноразовый режим применения миграций и выхода —
//! используется как отдельный шаг в деплое перед запуском самого сервера.
use clap::Parser;
use sqlx::postgres::PgPoolOptions;
use std::net::SocketAddr;
@@ -112,10 +118,26 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let db_url =
std::env::var("DATABASE_URL").expect("КРИТИЧЕСКАЯ ОШИБКА: DATABASE_URL не задан в .env!");
let pool = PgPoolOptions::new()
.max_connections(20)
.connect(db_url.trim())
.await?;
// На WSL2/Docker DNS может ответить "name resolution failure" в первые секунды
// после старта контейнера, даже когда db уже healthy. Делаем несколько попыток.
let pool = {
let url = db_url.trim();
let mut last_err = None;
let mut attempt = 0u8;
loop {
attempt += 1;
match PgPoolOptions::new().max_connections(20).connect(url).await {
Ok(p) => break p,
Err(e) if attempt < 5 => {
tracing::warn!("БД недоступна (попытка {}/5): {}. Повтор через 3с…", attempt, e);
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
last_err = Some(e);
}
Err(e) => return Err(e.into()),
}
let _ = last_err;
}
};
// Режим миграций требует только DATABASE_URL — ни ключей, ни токенов.
// Используется как one-shot шаг в пайплайне деплоя перед стартом приложения.