77 lines
2.7 KiB
Python
77 lines
2.7 KiB
Python
|
|
"""
|
|||
|
|
PostgreSQL Database Service
|
|||
|
|
"""
|
|||
|
|
import asyncpg
|
|||
|
|
from typing import Optional, Dict, Any, List
|
|||
|
|
from ..config import settings
|
|||
|
|
import logging
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class DatabaseService:
|
|||
|
|
"""Сервис для работы с PostgreSQL"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
self.pool: Optional[asyncpg.Pool] = None
|
|||
|
|
|
|||
|
|
async def connect(self):
|
|||
|
|
"""Создает пул подключений к PostgreSQL"""
|
|||
|
|
try:
|
|||
|
|
self.pool = await asyncpg.create_pool(
|
|||
|
|
host=settings.postgres_host,
|
|||
|
|
port=settings.postgres_port,
|
|||
|
|
database=settings.postgres_db,
|
|||
|
|
user=settings.postgres_user,
|
|||
|
|
password=settings.postgres_password,
|
|||
|
|
min_size=5,
|
|||
|
|
max_size=20,
|
|||
|
|
command_timeout=60
|
|||
|
|
)
|
|||
|
|
logger.info(f"✅ PostgreSQL connected: {settings.postgres_host}:{settings.postgres_port}/{settings.postgres_db}")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ PostgreSQL connection error: {e}")
|
|||
|
|
raise
|
|||
|
|
|
|||
|
|
async def disconnect(self):
|
|||
|
|
"""Закрывает пул подключений"""
|
|||
|
|
if self.pool:
|
|||
|
|
await self.pool.close()
|
|||
|
|
logger.info("PostgreSQL pool closed")
|
|||
|
|
|
|||
|
|
async def execute(self, query: str, *args) -> str:
|
|||
|
|
"""Выполняет SQL запрос без возврата данных"""
|
|||
|
|
async with self.pool.acquire() as conn:
|
|||
|
|
return await conn.execute(query, *args)
|
|||
|
|
|
|||
|
|
async def fetch_one(self, query: str, *args) -> Optional[Dict[str, Any]]:
|
|||
|
|
"""Возвращает одну запись"""
|
|||
|
|
async with self.pool.acquire() as conn:
|
|||
|
|
row = await conn.fetchrow(query, *args)
|
|||
|
|
return dict(row) if row else None
|
|||
|
|
|
|||
|
|
async def fetch_all(self, query: str, *args) -> List[Dict[str, Any]]:
|
|||
|
|
"""Возвращает все записи"""
|
|||
|
|
async with self.pool.acquire() as conn:
|
|||
|
|
rows = await conn.fetch(query, *args)
|
|||
|
|
return [dict(row) for row in rows]
|
|||
|
|
|
|||
|
|
async def fetch_val(self, query: str, *args):
|
|||
|
|
"""Возвращает одно значение"""
|
|||
|
|
async with self.pool.acquire() as conn:
|
|||
|
|
return await conn.fetchval(query, *args)
|
|||
|
|
|
|||
|
|
async def health_check(self) -> bool:
|
|||
|
|
"""Проверка здоровья БД"""
|
|||
|
|
try:
|
|||
|
|
result = await self.fetch_val("SELECT 1")
|
|||
|
|
return result == 1
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Database health check failed: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
|
|||
|
|
# Глобальный экземпляр
|
|||
|
|
db = DatabaseService()
|
|||
|
|
|