Skip to content

Commit b9d3724

Browse files
committed
feat: added db connection retries
1 parent f2b8ea4 commit b9d3724

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

docs/getting-started/installation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ volumes:
9595
# --- Application Settings (можно оставить по умолчанию) ---
9696
LOG_LEVEL=INFO
9797
GC_INTERVAL_SECONDS=60
98+
DB_CONN_RETRIES=5
99+
DB_CONN_RETRY_DELAY=5
98100
```
99101

100102
#### Шаг 4: Запустите DeBot

docs/system-architecture/configuration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
| `DB_NAME` | Имя базы данных. | `userbot_db` |
2121
| `DB_USER` | Имя пользователя для подключения к БД. | `userbot` |
2222
| `DB_PASS` | Пароль пользователя для подключения к БД. | `userbot_password` |
23+
| `DB_CONN_RETRIES` | Количество попыток подключения к БД при старте. | `5` |
24+
| `DB_CONN_RETRY_DELAY`| Задержка в секундах между попытками подключения. | `5` |
2325

2426
### Приложение
2527

userbot/src/config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616
DB_USER: str = os.getenv("DB_USER", "userbot")
1717
DB_PASS: str = os.getenv("DB_PASS", "userbot_password")
1818
DB_NAME: str = os.getenv("DB_NAME", "userbot_db")
19+
# New: Connection retry settings
20+
DB_CONN_RETRIES: int = int(os.getenv("DB_CONN_RETRIES", 5))
21+
DB_CONN_RETRY_DELAY: int = int(os.getenv("DB_CONN_RETRY_DELAY", 5))
22+
1923

2024
# --- Application Settings ---
2125
MODULE_FOLDER: str = "userbot.modules"
2226
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO").upper()
2327

2428
# --- Scheduler Settings ---
25-
GC_INTERVAL_SECONDS: int = int(os.getenv("GC_INTERVAL_SECONDS", 30))
29+
GC_INTERVAL_SECONDS: int = int(os.getenv("GC_INTERVAL_SECONDS", 60))
2630
AUTO_UPDATE_ENABLED: bool = os.getenv("AUTO_UPDATE_ENABLED", "False").lower() in ('true', '1', 't')
2731
AUTO_UPDATE_INTERVAL_MINUTES: int = int(os.getenv("AUTO_UPDATE_INTERVAL_MINUTES", 1440))
2832
DEPLOY_TYPE: str = os.getenv("DEPLOY_TYPE", "source") # 'source' or 'image'

userbot/src/db/session.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import logging
2+
import asyncio
3+
import sys
24
from contextlib import asynccontextmanager
35
from typing import AsyncGenerator
46

57
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
68
from sqlalchemy.exc import SQLAlchemyError
79

8-
from userbot.src.config import DB_TYPE, DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME
10+
from userbot.src.config import (
11+
DB_TYPE, DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME,
12+
DB_CONN_RETRIES, DB_CONN_RETRY_DELAY
13+
)
914
from userbot.src.db.models import Base
1015

1116
logger: logging.Logger = logging.getLogger(__name__)
@@ -31,11 +36,33 @@
3136

3237
async def initialize_database() -> None:
3338
"""
34-
Creates all tables in the database based on the SQLAlchemy models.
39+
Connects to the database and creates all tables based on the SQLAlchemy models.
40+
Includes a retry mechanism to handle database startup delays.
3541
"""
36-
async with async_engine.begin() as conn:
37-
await conn.run_sync(Base.metadata.create_all)
38-
logger.info("Database schema initialization check complete.")
42+
for attempt in range(DB_CONN_RETRIES):
43+
try:
44+
async with async_engine.begin() as conn:
45+
await conn.run_sync(Base.metadata.create_all)
46+
logger.info("Database schema initialization check complete.")
47+
return # Success, exit the function
48+
except (ConnectionRefusedError, OSError) as e:
49+
if attempt < DB_CONN_RETRIES - 1:
50+
logger.warning(
51+
f"Database connection failed (attempt {attempt + 1}/{DB_CONN_RETRIES}): {e}. "
52+
f"Retrying in {DB_CONN_RETRY_DELAY} seconds..."
53+
)
54+
await asyncio.sleep(DB_CONN_RETRY_DELAY)
55+
else:
56+
logger.critical(
57+
f"Could not connect to the database after {DB_CONN_RETRIES} attempts. "
58+
"Please ensure the database is running and the .env file is configured correctly."
59+
)
60+
raise # Re-raise the final exception to stop the application
61+
62+
# This part should not be reachable if all retries fail, but as a safeguard:
63+
logger.critical("Exhausted all retries to connect to the database. Exiting.")
64+
sys.exit(1)
65+
3966

4067
@asynccontextmanager
4168
async def get_db() -> AsyncGenerator[AsyncSession, None]:

0 commit comments

Comments
 (0)