feat: add A-card operations frontend and backend foundation
This commit is contained in:
@@ -26,6 +26,7 @@ from venv import logger
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
from pydantic import Field, field_validator, model_validator
|
||||
from pydantic_settings import BaseSettings, NoDecode, SettingsConfigDict
|
||||
from sqlalchemy.engine import make_url
|
||||
|
||||
|
||||
# ── AES 解密核心函数 ────────────────────────────────────────────────────────
|
||||
@@ -63,6 +64,43 @@ class Settings(BaseSettings):
|
||||
),
|
||||
description="SQLAlchemy async URI for the platform MySQL.",
|
||||
)
|
||||
operations_database_url: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"SQLAlchemy async URI for the isolated model_operations database. "
|
||||
"When omitted it reuses DATABASE_URL credentials and switches only "
|
||||
"the schema name to model_operations."
|
||||
),
|
||||
)
|
||||
platform_read_database_url: str | None = Field(
|
||||
default=None,
|
||||
description="Read-only model_platform connection used by operations APIs.",
|
||||
)
|
||||
deploy_database_url: str | None = Field(
|
||||
default=None,
|
||||
description="Read-only model_deploy connection used by operations APIs.",
|
||||
)
|
||||
|
||||
# ── operations Redis accelerator ─────────────────────────────
|
||||
redis_url: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"Optional Redis URL for operations query cache and event Streams. "
|
||||
"MySQL remains the source of truth when Redis is unavailable."
|
||||
),
|
||||
)
|
||||
redis_socket_connect_timeout_seconds: float = Field(default=2.0, gt=0, le=30)
|
||||
redis_socket_timeout_seconds: float = Field(default=2.0, gt=0, le=30)
|
||||
operations_cache_ttl_seconds: int = Field(default=300, ge=10, le=86400)
|
||||
operations_redis_prefix: str = Field(default="model-platform:operations")
|
||||
operations_event_stream: str = Field(
|
||||
default="model-platform:operations:events"
|
||||
)
|
||||
operations_event_stream_maxlen: int = Field(default=10000, ge=100)
|
||||
operations_data_mode: str = Field(
|
||||
default="database",
|
||||
description="Operations data source: database or mock.",
|
||||
)
|
||||
|
||||
# ── JWT ───────────────────────────────────────────────────────
|
||||
jwt_secret: str = Field(
|
||||
@@ -268,6 +306,23 @@ class Settings(BaseSettings):
|
||||
# print(values[key])
|
||||
return values
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _derive_operations_database_url(self) -> "Settings":
|
||||
"""Default the operations database to the platform server credentials."""
|
||||
if not self.operations_database_url:
|
||||
platform_url = make_url(self.database_url)
|
||||
self.operations_database_url = platform_url.set(
|
||||
database="model_operations"
|
||||
).render_as_string(hide_password=False)
|
||||
if not self.platform_read_database_url:
|
||||
self.platform_read_database_url = self.database_url
|
||||
if not self.deploy_database_url:
|
||||
platform_url = make_url(self.database_url)
|
||||
self.deploy_database_url = platform_url.set(
|
||||
database="model_deploy"
|
||||
).render_as_string(hide_password=False)
|
||||
return self
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
|
||||
Reference in New Issue
Block a user