From b10a2cd8e165eaf458c006760cdc4a350bb6625b Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 6 Nov 2025 17:27:10 +0100 Subject: [PATCH] Moved database module to separate library --- requirements.txt | 1 + src/db.py | 132 ----------------------------------------------- src/main.py | 4 +- 3 files changed, 3 insertions(+), 134 deletions(-) delete mode 100644 src/db.py diff --git a/requirements.txt b/requirements.txt index da6a3fc..1f8ec46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ fastapi==0.118.2 feedparser==6.0.12 h11==0.16.0 idna==3.10 +lib-db-module @ git+https://git.gansejunge.com/notifier/lib-db-module.git@main lib-secret-manager @ git+https://git.gansejunge.com/notifier/lib-secret-manager.git@main lib-uvicorn-config @ git+https://git.gansejunge.com/notifier/lib-uvicorn-config.git@main mysql-connector-python==9.4.0 diff --git a/src/db.py b/src/db.py deleted file mode 100644 index 983c85b..0000000 --- a/src/db.py +++ /dev/null @@ -1,132 +0,0 @@ -from mysql.connector import pooling, Error -import threading -from secret_manager import return_credentials -import os -import time -from simple_logger_handler import setup_logger - -db_username = return_credentials("/etc/secrets/db_username") -db_password = return_credentials("/etc/secrets/db_password") -db_host = os.getenv("SERVICE_RR_DB_HOST","localhost") -db_database = os.getenv("SERVICE_RR_DB_HOST_DATABASE","app") - -logger = setup_logger(__name__) - - -MAX_RETRIES = 5 -RETRY_DELAY = 5 -HEALTHCHECK_INTERVAL = 60 - -MYSQL_CONFIG = { - "host": db_host, - "user": db_username, - "password": db_password, - "database": db_database, - "connection_timeout": 10 -} - - -_pool_lock = threading.Lock() -_connection_pool = None -_health_thread = None -_stop_healthcheck = threading.Event() - - -def create_connection_pool(): - global _connection_pool - with _pool_lock: - if _connection_pool is not None: - logger.debug("[MySQL] Pool already exists, returning existing pool") - return - for attempt in range (1,MAX_RETRIES+1): - try: - logger.info(f"[MySQL] Attempt {attempt} to connect...") - pool = pooling.MySQLConnectionPool( - pool_name="royalRoadPool", - pool_size=5, - pool_reset_session=True, - **MYSQL_CONFIG - ) - with _pool_lock: - _connection_pool = pool - logger.info("[MySQL] Pool created", extra={"pool_name": pool.pool_name}) - return - - except Error as e: - logger.warning(f"[MySQL] Attempt {attempt} failed: {e}") - if attempt < MAX_RETRIES: - logger.debug(f"[MySQL] Retrying in {RETRY_DELAY} seconds...") - time.sleep(RETRY_DELAY) - - logger.critical(f"[MySQL] Failed to connect after {MAX_RETRIES} attempts.") - raise RuntimeError("MySQL pool initialization failed") - -def close_connection_pool(): - global _connection_pool - with _pool_lock: - if _connection_pool: - logger.debug(f"[MySQL] Closing pool: {_connection_pool}") - _connection_pool = None - logger.info("[MySQL] Connection pool closed") - _stop_healthcheck.set() - logger.debug("[MySQL] Healthcheck stop flag set") - -def get_connection_pool(): - global _connection_pool - with _pool_lock: - if _connection_pool is None: - logger.debug("[MySQL] No pool found, creating one") - create_connection_pool() - else: - logger.debug(f"[MySQL] Returning existing pool: {_connection_pool}") - return _connection_pool - -def get_db(): - pool = get_connection_pool() - logger.debug(f"[MySQL] Acquiring connection from pool: {pool}") - conn = pool.get_connection() - - try: - conn.ping(reconnect=True, attempts=3, delay=1) - logger.debug("[MySQL] Connection alive") - except Error as e: - logger.warning(f"[MySQL] Connection dead, recreating pool: {e}") - create_connection_pool() - pool = get_connection_pool() - conn = pool.get_connection() - logger.debug("[MySQL] Reconnected successfully") - - try: - yield conn - finally: - if conn and conn.is_connected(): - conn.close() - logger.debug("[MySQL] Connection returned to pool") - -def _pool_healthcheck(): - while not _stop_healthcheck.is_set(): - time.sleep(HEALTHCHECK_INTERVAL) - with _pool_lock: - pool = _connection_pool - if not pool: - logger.debug("[MySQL] Healthcheck skipped, pool not initialized") - continue - try: - conn = pool.get_connection() - conn.ping(reconnect=True, attempts=3, delay=1) - conn.close() - logger.debug(f"[MySQL] Pool healthcheck succeeded") - except Error as e: - logger.warning(f"[MySQL] Pool healthcheck failed: {e}") - create_connection_pool() - - -def start_healthcheck_thread(): - global _health_thread - if _health_thread and _health_thread.is_alive(): - logger.debug("[MySQL] Healthcheck thread already running") - return - _stop_healthcheck.clear() - _health_thread = threading.Thread(target=_pool_healthcheck, daemon=True) - _health_thread.start() - logger.info("[MySQL] Healthcheck thread started.") \ No newline at end of file diff --git a/src/main.py b/src/main.py index a026578..ec38122 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,7 @@ from fastapi import FastAPI, Depends, HTTPException, Response, Request import uvicorn from contextlib import asynccontextmanager -from db import get_db, create_connection_pool, close_connection_pool, start_healthcheck_thread +from db_module import get_db, create_connection_pool, close_connection_pool, start_healthcheck_thread from simple_logger_handler import setup_logger, LOG_LEVEL from feed_handler import grab_latest_chapter_information from send_notification import send_notification @@ -18,7 +18,7 @@ async def lifespan(app: FastAPI): logger.info("[App] Starting application...") logger.info("[DB] Creating MySQL connection pool...") - create_connection_pool() + create_connection_pool("royalRoadPool") start_healthcheck_thread() logger.info("[DB] MySQL healthcheck thread started.")