Files
RuoYi-Vue3-FastAPI/ruoyi-fastapi-backend/config/database.py
T
insistence 5cd6d4788a feat: 新增多worker运行支持 (#76)
* feat: 定时任务新增redis分布式锁以在多worker下正常运行

* refactor: 重构日志系统以支持多worker

* perf: 增强scheduler在多worker下的调度机制

* perf: 增强锁丢失调度逻辑与异常容错

* perf: 优化trace中间件和日志打印显示

* chore: 更新.gitignore规则

* perf: 优化database的engine和session创建方法

* perf: 优化scheduler内部的sqlalchemy日志显示

* perf: 优化scheduler和应用生命周期

* fix: 修复重新获取锁时重复调用的问题

* perf: 优化函数无用参数

* perf: 优化env配置

* fix: 修复lint错误
2026-02-06 09:07:46 +08:00

110 lines
3.5 KiB
Python

from urllib.parse import quote_plus
from sqlalchemy import Engine, create_engine
from sqlalchemy.ext.asyncio import AsyncAttrs, AsyncEngine, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, sessionmaker
from config.env import DataBaseConfig
def build_async_sqlalchemy_database_url() -> str:
"""
构建异步 SQLAlchemy 数据库连接 URL
:return: 异步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+asyncpg://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+asyncmy://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
ASYNC_SQLALCHEMY_DATABASE_URL = build_async_sqlalchemy_database_url()
def build_sync_sqlalchemy_database_url() -> str:
"""
构建同步 SQLAlchemy 数据库连接 URL
:return: 同步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+psycopg2://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
SYNC_SQLALCHEMY_DATABASE_URL = build_sync_sqlalchemy_database_url()
def create_async_db_engine(echo: bool | None = None) -> AsyncEngine:
"""
创建异步 SQLAlchemy Engine
:param echo: 可选,是否输出 SQLAlchemy SQL 日志
:return: 异步 SQLAlchemy Engine
"""
return create_async_engine(
ASYNC_SQLALCHEMY_DATABASE_URL,
echo=DataBaseConfig.db_echo if echo is None else echo,
max_overflow=DataBaseConfig.db_max_overflow,
pool_size=DataBaseConfig.db_pool_size,
pool_recycle=DataBaseConfig.db_pool_recycle,
pool_timeout=DataBaseConfig.db_pool_timeout,
)
def create_sync_db_engine(echo: bool | None = None) -> Engine:
"""
创建同步 SQLAlchemy Engine
:param echo: 可选,是否输出 SQLAlchemy SQL 日志
:return: 同步 SQLAlchemy Engine
"""
return create_engine(
SYNC_SQLALCHEMY_DATABASE_URL,
echo=DataBaseConfig.db_echo if echo is None else echo,
max_overflow=DataBaseConfig.db_max_overflow,
pool_size=DataBaseConfig.db_pool_size,
pool_recycle=DataBaseConfig.db_pool_recycle,
pool_timeout=DataBaseConfig.db_pool_timeout,
)
def create_async_session_local(engine: AsyncEngine) -> async_sessionmaker:
"""
创建异步 Session 工厂
:param engine: 异步 SQLAlchemy Engine
:return: 异步 Session 工厂
"""
return async_sessionmaker(autocommit=False, autoflush=False, bind=engine)
def create_sync_session_local(engine: Engine) -> sessionmaker:
"""
创建同步 Session 工厂
:param engine: 同步 SQLAlchemy Engine
:return: 同步 Session 工厂
"""
return sessionmaker(autocommit=False, autoflush=False, bind=engine)
async_engine = create_async_db_engine()
AsyncSessionLocal = create_async_session_local(async_engine)
class Base(AsyncAttrs, DeclarativeBase):
pass