Enhance bot functionality and refactor database interactions
- Added `ca-certificates` installation to Dockerfile for improved network security. - Updated health check command in Dockerfile to include better timeout handling. - Refactored `run_helper.py` to implement proper signal handling and logging during shutdown. - Transitioned database operations to an asynchronous model in `async_db.py`, improving performance and responsiveness. - Updated database schema to support new foreign key relationships and optimized indexing for better query performance. - Enhanced various bot handlers to utilize async database methods, improving overall efficiency and user experience. - Removed obsolete database and fix scripts to streamline the project structure.
This commit is contained in:
@@ -8,12 +8,13 @@ import logging
|
||||
from aiohttp import web
|
||||
from typing import Optional, Dict, Any, Protocol
|
||||
from .metrics import metrics
|
||||
import time
|
||||
|
||||
|
||||
class DatabaseProvider(Protocol):
|
||||
"""Protocol for database operations."""
|
||||
|
||||
async def fetch_one(self, query: str) -> Optional[Dict[str, Any]]:
|
||||
async def fetch_one(self, query: str, params: tuple = ()) -> Optional[Dict[str, Any]]:
|
||||
"""Execute query and return single result."""
|
||||
...
|
||||
|
||||
@@ -37,12 +38,16 @@ class UserMetricsCollector:
|
||||
try:
|
||||
# Проверяем, есть ли метод fetch_one (асинхронная БД)
|
||||
if hasattr(db, 'fetch_one'):
|
||||
# Используем UNIX timestamp для сравнения с date_changed
|
||||
current_timestamp = int(time.time())
|
||||
one_day_ago = current_timestamp - (24 * 60 * 60) # 24 часа назад
|
||||
|
||||
active_users_query = """
|
||||
SELECT COUNT(DISTINCT user_id) as active_users
|
||||
FROM our_users
|
||||
WHERE date_changed > datetime('now', '-1 day')
|
||||
WHERE date_changed > ?
|
||||
"""
|
||||
result = await db.fetch_one(active_users_query)
|
||||
result = await db.fetch_one(active_users_query, (one_day_ago,))
|
||||
if result:
|
||||
metrics.set_active_users(result['active_users'], 'daily')
|
||||
self.logger.debug(f"Updated active users: {result['active_users']}")
|
||||
@@ -55,16 +60,19 @@ class UserMetricsCollector:
|
||||
import asyncio
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
current_timestamp = int(time.time())
|
||||
one_day_ago = current_timestamp - (24 * 60 * 60) # 24 часа назад
|
||||
|
||||
active_users_query = """
|
||||
SELECT COUNT(DISTINCT user_id) as active_users
|
||||
FROM our_users
|
||||
WHERE date_changed > datetime('now', '-1 day')
|
||||
WHERE date_changed > ?
|
||||
"""
|
||||
|
||||
def sync_db_query():
|
||||
try:
|
||||
db.connect()
|
||||
db.cursor.execute(active_users_query)
|
||||
db.cursor.execute(active_users_query, (one_day_ago,))
|
||||
result = db.cursor.fetchone()
|
||||
return result[0] if result else 0
|
||||
finally:
|
||||
@@ -172,11 +180,24 @@ class MetricsExporter:
|
||||
|
||||
async def stop(self):
|
||||
"""Stop the metrics server."""
|
||||
if self.site:
|
||||
await self.site.stop()
|
||||
if self.runner:
|
||||
await self.runner.cleanup()
|
||||
self.logger.info("Metrics server stopped")
|
||||
try:
|
||||
if self.site:
|
||||
await self.site.stop()
|
||||
self.logger.info("Metrics server site stopped")
|
||||
|
||||
if self.runner:
|
||||
await self.runner.cleanup()
|
||||
self.logger.info("Metrics server runner cleaned up")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error stopping metrics server: {e}")
|
||||
finally:
|
||||
# Очищаем ссылки
|
||||
self.site = None
|
||||
self.runner = None
|
||||
# Даем время на закрытие всех соединений
|
||||
await asyncio.sleep(0.1)
|
||||
self.logger.info("Metrics server stopped")
|
||||
|
||||
async def metrics_handler(self, request: web.Request) -> web.Response:
|
||||
"""Handle /metrics endpoint for Prometheus."""
|
||||
@@ -249,10 +270,21 @@ class MetricsManager:
|
||||
async def stop(self):
|
||||
"""Stop metrics collection and export."""
|
||||
try:
|
||||
await self.collector.stop()
|
||||
await self.exporter.stop()
|
||||
self.logger.info("Metrics manager stopped successfully")
|
||||
# Останавливаем background collector
|
||||
if hasattr(self, 'collector'):
|
||||
await self.collector.stop()
|
||||
self.logger.info("Background metrics collector stopped")
|
||||
|
||||
# Останавливаем exporter
|
||||
if hasattr(self, 'exporter'):
|
||||
await self.exporter.stop()
|
||||
self.logger.info("Metrics exporter stopped")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error stopping metrics manager: {e}")
|
||||
raise
|
||||
# Не вызываем raise, чтобы не прерывать процесс завершения
|
||||
finally:
|
||||
# Очищаем ссылки
|
||||
self.collector = None
|
||||
self.exporter = None
|
||||
self.logger.info("Metrics manager stopped successfully")
|
||||
|
||||
Reference in New Issue
Block a user