- sql/schema.sql: users/authorizations/auth_scenes/usage_logs + sessions 建表 - db.py: aiomysql 连接池,lifespan 内初始化与释放 - wechat_api.py: access_token 缓存 + 临时二维码创建 - auth.py: /auth/create_scene、/auth/status,handle_scan 事务内幂等处理扫码 - wechat.py: 接入 DB 生命周期,处理 subscribe/SCAN 事件;移除多余的 openid query 参数 - 首次关注赠送 7 天免费授权,has_claimed_free 条件更新保证幂等 - config.py/.env.example: 新增 FREE_AUTH_DAYS/SCENE_TTL_SECONDS/SESSION_TTL_HOURS
59 lines
1.3 KiB
Python
59 lines
1.3 KiB
Python
"""
|
||
MySQL 连接池管理(aiomysql)
|
||
|
||
用法:
|
||
await init_pool() # 应用启动时调用
|
||
async with acquire() as conn:
|
||
...
|
||
await close_pool() # 应用关闭时调用
|
||
|
||
连接池开启 autocommit,单条语句自动提交;需要事务时显式调用 conn.begin() / conn.commit()。
|
||
"""
|
||
|
||
from contextlib import asynccontextmanager
|
||
from typing import Optional
|
||
|
||
import aiomysql
|
||
|
||
from config import MYSQL_DB, MYSQL_HOST, MYSQL_PASSWORD, MYSQL_PORT, MYSQL_USER
|
||
|
||
_pool: Optional[aiomysql.Pool] = None
|
||
|
||
|
||
async def init_pool() -> None:
|
||
"""创建全局连接池"""
|
||
global _pool
|
||
_pool = await aiomysql.create_pool(
|
||
host=MYSQL_HOST,
|
||
port=MYSQL_PORT,
|
||
user=MYSQL_USER,
|
||
password=MYSQL_PASSWORD,
|
||
db=MYSQL_DB,
|
||
charset="utf8mb4",
|
||
autocommit=True,
|
||
minsize=1,
|
||
maxsize=10,
|
||
)
|
||
|
||
|
||
async def close_pool() -> None:
|
||
"""关闭连接池"""
|
||
global _pool
|
||
if _pool is not None:
|
||
_pool.close()
|
||
await _pool.wait_closed()
|
||
_pool = None
|
||
|
||
|
||
def get_pool() -> aiomysql.Pool:
|
||
if _pool is None:
|
||
raise RuntimeError("MySQL 连接池未初始化,请先调用 init_pool()")
|
||
return _pool
|
||
|
||
|
||
@asynccontextmanager
|
||
async def acquire():
|
||
"""从连接池借出一个连接"""
|
||
async with get_pool().acquire() as conn:
|
||
yield conn
|