DB and FastAPI: Reconnect if DB goes down, switch to lifespan events in FastAPI, ensure safe startup/shutdown.
This commit is contained in:
parent
2a8d06a373
commit
799ecdda67
1
.gitignore
vendored
1
.gitignore
vendored
@ -168,3 +168,4 @@ cython_debug/
|
|||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
test.py
|
||||||
|
|||||||
25
src/db.py
25
src/db.py
@ -24,17 +24,20 @@ MYSQL_CONFIG = {
|
|||||||
_pool_lock = threading.Lock()
|
_pool_lock = threading.Lock()
|
||||||
_connection_pool = None
|
_connection_pool = None
|
||||||
|
|
||||||
|
|
||||||
def create_connection_pool():
|
def create_connection_pool():
|
||||||
global _connection_pool
|
global _connection_pool
|
||||||
for attempt in range(1, MAX_RETRIES+1):
|
for attempt in range(1, MAX_RETRIES+1):
|
||||||
try:
|
try:
|
||||||
print(f"[MySQL] Attempt {attempt} to connect...")
|
print(f"[MySQL] Attempt {attempt} to connect...")
|
||||||
_connection_pool = mysql.connector.pooling.MySQLConnectionPool(
|
pool = mysql.connector.pooling.MySQLConnectionPool(
|
||||||
pool_name="mypool",
|
pool_name="mypool",
|
||||||
pool_size=5,
|
pool_size=5,
|
||||||
pool_reset_session=True,
|
pool_reset_session=True,
|
||||||
**MYSQL_CONFIG
|
**MYSQL_CONFIG
|
||||||
)
|
)
|
||||||
|
with _pool_lock:
|
||||||
|
_connection_pool = pool
|
||||||
print("[MySQL] Connection pool created successfully.")
|
print("[MySQL] Connection pool created successfully.")
|
||||||
return
|
return
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
@ -44,6 +47,15 @@ def create_connection_pool():
|
|||||||
print(f"[MySQL] Failed to connect after {MAX_RETRIES} attempts — exiting.")
|
print(f"[MySQL] Failed to connect after {MAX_RETRIES} attempts — exiting.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def close_connection_pool():
|
||||||
|
global _connection_pool
|
||||||
|
with _pool_lock:
|
||||||
|
if _connection_pool:
|
||||||
|
_connection_pool = None
|
||||||
|
print("[MySQL] Connection pool closed.")
|
||||||
|
|
||||||
|
|
||||||
def get_connection_pool():
|
def get_connection_pool():
|
||||||
global _connection_pool
|
global _connection_pool
|
||||||
with _pool_lock:
|
with _pool_lock:
|
||||||
@ -51,11 +63,18 @@ def get_connection_pool():
|
|||||||
create_connection_pool()
|
create_connection_pool()
|
||||||
return _connection_pool
|
return _connection_pool
|
||||||
|
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
pool = get_connection_pool()
|
pool = get_connection_pool()
|
||||||
conn = pool.get_connection()
|
try:
|
||||||
|
conn = pool.get_connection()
|
||||||
|
if not conn.is_connected():
|
||||||
|
conn.reconnect(attempts=MAX_RETRIES, delay=RETRY_DELAY)
|
||||||
|
except Exception:
|
||||||
|
create_connection_pool()
|
||||||
|
pool = get_connection_pool()
|
||||||
|
conn = pool.get_connection()
|
||||||
try:
|
try:
|
||||||
yield conn
|
yield conn
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|||||||
21
src/main.py
21
src/main.py
@ -1,4 +1,4 @@
|
|||||||
from fastapi import FastAPI, Depends, HTTPException
|
from fastapi import FastAPI, Depends, HTTPException, Request
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.security.api_key import APIKeyHeader
|
from fastapi.security.api_key import APIKeyHeader
|
||||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||||
@ -6,12 +6,13 @@ from typing import Optional,List
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from validator import is_valid_platform,is_valid_token,verify_api_key
|
from validator import is_valid_platform,is_valid_token,verify_api_key
|
||||||
from secret_handler import encrypt_token
|
from secret_handler import encrypt_token
|
||||||
from db import get_db
|
from db import get_db, create_connection_pool, close_connection_pool
|
||||||
from logger_handler import setup_logger
|
from logger_handler import setup_logger
|
||||||
import uuid
|
import uuid
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from uvicorn_logging_config import LOGGING_CONFIG
|
from uvicorn_logging_config import LOGGING_CONFIG
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -31,10 +32,24 @@ class TokenRequest(BaseModel):
|
|||||||
locale : Optional[str] = None
|
locale : Optional[str] = None
|
||||||
topics : Optional[List[str]] = None
|
topics : Optional[List[str]] = None
|
||||||
|
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def lifespan(app: FastAPI):
|
||||||
|
logger.info("Starting application...")
|
||||||
|
|
||||||
|
logger.info("Creating MySQL connection pool...")
|
||||||
|
create_connection_pool()
|
||||||
|
|
||||||
|
yield
|
||||||
|
logger.info("Closing MySQL connection pool...")
|
||||||
|
close_connection_pool()
|
||||||
|
|
||||||
|
|
||||||
api = FastAPI(
|
api = FastAPI(
|
||||||
title="Device Token Management",
|
title="Device Token Management",
|
||||||
description="API for requesting tokens",
|
description="API for requesting tokens",
|
||||||
version="1.0.0"
|
version="1.0.0",
|
||||||
|
lifespan=lifespan
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user