checkpoint: SQLite 清理——业务/测试层统一 PostgreSQL(删 aiosqlite/fakeredis)
- setting: DATABASE_TYPE 收窄为 postgres,DB_URI/ASYNC_DB_URI 去 sqlite 分支 - database: create_async_engine_and_session 去 sqlite 分支(同步 psycopg 引擎保留给 jobstore) - number_gen: 去 DATABASE_TYPE 非 postgres 早退(advisory lock 恒定走 PG) - chat/crud: 删 SqliteDb 分支(agno 无硬依赖) - pyproject/requirements/uv.lock: 删 aiosqlite、fakeredis;conftest 口径注释同步 - test_stat_analysis_tc: docstring 口径 SQLite→PG
This commit is contained in:
@@ -3,7 +3,6 @@ from typing import Any
|
||||
from agno.db.base import SessionType
|
||||
from agno.db.mysql import MySQLDb
|
||||
from agno.db.postgres import PostgresDb
|
||||
from agno.db.sqlite import SqliteDb
|
||||
from agno.session.team import TeamSession
|
||||
|
||||
from app.config.setting import settings
|
||||
@@ -34,7 +33,6 @@ class ChatSessionCRUD:
|
||||
db_mapping = {
|
||||
"mysql": lambda: MySQLDb(db_url=db_uri, db_schema=settings.DATABASE_NAME, create_schema=False),
|
||||
"postgres": lambda: PostgresDb(db_url=db_uri, db_schema="public", create_schema=False),
|
||||
"sqlite": lambda: SqliteDb(db_file=db_uri.replace("sqlite:///", "")),
|
||||
}
|
||||
|
||||
if db_type not in db_mapping:
|
||||
|
||||
@@ -10,7 +10,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
from app.common.enums import EnvironmentEnum
|
||||
from app.config.path_conf import ENV_DIR, STATIC_DIR
|
||||
|
||||
|
||||
# JWT 开发默认密钥:仅允许 DEV 环境使用,生产命中即拒绝启动
|
||||
_DEV_DEFAULT_SECRET_KEY = "dpb-dev-secret-key-do-not-use-in-production"
|
||||
|
||||
@@ -110,8 +109,8 @@ class Settings(BaseSettings):
|
||||
AUTOFETCH: bool | None = None # AUTOFLUSH 别名(优先级高于 AUTOFLUSH,兼容旧环境变量名)
|
||||
EXPIRE_ON_COMMIT: bool = False # 是否在提交时过期
|
||||
|
||||
# 数据库连接(生产 PostgreSQL;测试套件用 SQLite)
|
||||
DATABASE_TYPE: Literal["postgres", "sqlite"] = "postgres"
|
||||
# 数据库连接(开发与生产统一 PostgreSQL)
|
||||
DATABASE_TYPE: Literal["postgres"] = "postgres"
|
||||
DATABASE_HOST: str = "localhost"
|
||||
DATABASE_PORT: int = 5432
|
||||
DATABASE_USER: str = "dpb"
|
||||
@@ -305,19 +304,11 @@ class Settings(BaseSettings):
|
||||
|
||||
@property
|
||||
def ASYNC_DB_URI(self) -> str:
|
||||
if self.DATABASE_TYPE == "postgres":
|
||||
db_connect = f"postgresql+asyncpg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
||||
else:
|
||||
db_connect = f"sqlite+aiosqlite:///{self.DATABASE_NAME}.db"
|
||||
return db_connect
|
||||
return f"postgresql+asyncpg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
||||
|
||||
@property
|
||||
def DB_URI(self) -> str:
|
||||
if self.DATABASE_TYPE == "postgres":
|
||||
db_connect = f"postgresql+psycopg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
||||
else:
|
||||
db_connect = f"sqlite:///{self.DATABASE_NAME}.db"
|
||||
return db_connect
|
||||
return f"postgresql+psycopg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
||||
|
||||
@property
|
||||
def FASTAPI_CONFIG(self) -> dict[str, Any]:
|
||||
|
||||
@@ -49,29 +49,19 @@ def create_async_engine_and_session(db_url: str = settings.ASYNC_DB_URI) -> tupl
|
||||
- tuple[AsyncEngine, async_sessionmaker[AsyncSession]]: 异步数据库引擎和会话工厂。
|
||||
"""
|
||||
try:
|
||||
# 异步数据库引擎
|
||||
if settings.DATABASE_TYPE == "sqlite":
|
||||
async_engine = create_async_engine(
|
||||
url=db_url,
|
||||
echo=settings.DATABASE_ECHO,
|
||||
echo_pool=settings.ECHO_POOL,
|
||||
pool_pre_ping=settings.POOL_PRE_PING,
|
||||
future=settings.FUTURE,
|
||||
pool_recycle=settings.POOL_RECYCLE,
|
||||
)
|
||||
else:
|
||||
async_engine = create_async_engine(
|
||||
url=db_url,
|
||||
echo=settings.DATABASE_ECHO,
|
||||
echo_pool=settings.ECHO_POOL,
|
||||
pool_pre_ping=settings.POOL_PRE_PING,
|
||||
future=settings.FUTURE,
|
||||
pool_recycle=settings.POOL_RECYCLE,
|
||||
pool_size=settings.POOL_SIZE,
|
||||
max_overflow=settings.MAX_OVERFLOW,
|
||||
pool_timeout=settings.POOL_TIMEOUT,
|
||||
pool_use_lifo=settings.POOL_USE_LIFO,
|
||||
)
|
||||
# 异步数据库引擎(统一 PostgreSQL 连接池参数)
|
||||
async_engine = create_async_engine(
|
||||
url=db_url,
|
||||
echo=settings.DATABASE_ECHO,
|
||||
echo_pool=settings.ECHO_POOL,
|
||||
pool_pre_ping=settings.POOL_PRE_PING,
|
||||
future=settings.FUTURE,
|
||||
pool_recycle=settings.POOL_RECYCLE,
|
||||
pool_size=settings.POOL_SIZE,
|
||||
max_overflow=settings.MAX_OVERFLOW,
|
||||
pool_timeout=settings.POOL_TIMEOUT,
|
||||
pool_use_lifo=settings.POOL_USE_LIFO,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 数据库连接失败 {e}")
|
||||
raise
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
存量数据迁移:首次使用某序列名时由 seed_fn(服务端传入)从既有记录推算
|
||||
起始号(原扫描逻辑),此后全部走原子递增,不再扫描。
|
||||
"""
|
||||
from typing import Any, Awaitable, Callable
|
||||
from collections.abc import Awaitable, Callable
|
||||
|
||||
from sqlalchemy import select, text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -23,10 +23,6 @@ class NumberGenService:
|
||||
|
||||
@staticmethod
|
||||
async def _acquire_lock(db: AsyncSession, name: str) -> None:
|
||||
from app.config.setting import settings
|
||||
|
||||
if settings.DATABASE_TYPE != "postgres":
|
||||
return # sqlite 测试库无 advisory lock,退化为普通自增(单进程无并发竞争)
|
||||
# hashtextextended 对文本做稳定 64 位哈希,同名序列恒映射同一把锁
|
||||
await db.execute(text("SELECT pg_advisory_xact_lock(hashtextextended(:n, 0))"), {"n": name})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user