docs
This commit is contained in:
+26
-4
@@ -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 шаг в пайплайне деплоя перед стартом приложения.
|
||||
|
||||
Reference in New Issue
Block a user