feat(feishu): 添加飞书入站事件inbox和混合数据库协调功能 - 实现飞书入站事件持久化inbox机制,支持状态管理、租约锁定和重试退避 - 添加混合数据库基线协调工具,确保平台PostgreSQL结构安全对齐 - 增加运行组件心跳检测和readiness就绪检查机制 - 实现app_ticket事件的安全轮换和验证处理 - 添加生产环境运行编排和fail-closed安全机制 - 支持webhook快速确认和长连接独立进程处理 - 完善个人数据擦除时的待处理事件清理功能 ```
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
from sqlalchemy.engine import URL, make_url
|
|
from sqlalchemy.exc import ArgumentError
|
|
|
|
|
|
_DEFAULT_DATABASE_PORTS = {
|
|
"mysql": 3306,
|
|
"postgresql": 5432,
|
|
}
|
|
_PLATFORM_MIGRATION_BACKENDS = frozenset({"postgresql", "sqlite"})
|
|
|
|
DatabaseTarget = tuple[str, str, int | None, str]
|
|
|
|
|
|
def database_target(value: str | URL | None) -> DatabaseTarget | None:
|
|
"""Return a credential-free physical database identity."""
|
|
|
|
if not value:
|
|
return None
|
|
try:
|
|
url = make_url(value)
|
|
except (ArgumentError, TypeError, ValueError):
|
|
return None
|
|
backend = url.get_backend_name().lower()
|
|
return (
|
|
backend,
|
|
str(url.host or "").casefold(),
|
|
url.port or _DEFAULT_DATABASE_PORTS.get(backend),
|
|
str(url.database or ""),
|
|
)
|
|
|
|
|
|
def database_password(value: str | URL | None) -> str | None:
|
|
"""Return a configured password without including it in diagnostics."""
|
|
|
|
if not value:
|
|
return None
|
|
try:
|
|
password = make_url(value).password
|
|
except (ArgumentError, TypeError, ValueError):
|
|
return None
|
|
return str(password) if password is not None else None
|
|
|
|
|
|
def validate_platform_migration_target(
|
|
database_url: str | URL,
|
|
legacy_database_url: str | None,
|
|
) -> DatabaseTarget:
|
|
"""Fail closed before Alembic can connect to an unsafe database target."""
|
|
|
|
platform = database_target(database_url)
|
|
if platform is None:
|
|
raise RuntimeError("DATABASE_URL is not a valid platform database URL")
|
|
if platform[0] not in _PLATFORM_MIGRATION_BACKENDS:
|
|
raise RuntimeError(
|
|
"Platform migrations are supported only for PostgreSQL or local SQLite"
|
|
)
|
|
legacy = database_target(legacy_database_url)
|
|
if legacy is not None and platform == legacy:
|
|
raise RuntimeError(
|
|
"Refusing to migrate DATABASE_URL because it matches LEGACY_DATABASE_URL"
|
|
)
|
|
return platform
|