feat(database): bound async configuration writes

This commit is contained in:
InfinityPacer
2026-08-23 02:29:40 +08:00
parent 3d7fb44dc7
commit fc677a2bba
25 changed files with 408 additions and 48 deletions
+34 -1
View File
@@ -63,6 +63,7 @@ CONFIGURATION_EXCLUDED_ROOTS = (
APP_ROOT / "plugins",
APP_ROOT / "sdk",
APP_ROOT / "runtime" / "compat",
APP_ROOT / "testing",
)
@@ -85,6 +86,37 @@ def parse_source(path: Path) -> ast.Module:
return ast.parse(path.read_text(encoding="utf-8-sig"), filename=str(path))
def _is_type_checking_test(test: ast.expr) -> bool:
"""判断条件是否只在静态类型检查阶段成立。"""
return (
isinstance(test, ast.Name)
and test.id == "TYPE_CHECKING"
) or (
isinstance(test, ast.Attribute)
and isinstance(test.value, ast.Name)
and test.value.id == "typing"
and test.attr == "TYPE_CHECKING"
)
def iter_runtime_import_nodes(tree: ast.AST):
"""遍历运行期导入,排除 ``if TYPE_CHECKING`` 内的仅类型依赖。"""
parents: dict[ast.AST, ast.AST] = {}
for parent in ast.walk(tree):
for child in ast.iter_child_nodes(parent):
parents[child] = parent
for node in ast.walk(tree):
if not isinstance(node, (ast.Import, ast.ImportFrom)):
continue
parent = parents.get(node)
while parent is not None:
if isinstance(parent, ast.If) and _is_type_checking_test(parent.test):
break
parent = parents.get(parent)
else:
yield node
def collect_configuration_debt_baseline() -> dict[str, Any]:
"""收集宿主 canonical 代码直接读取 settings 和构造数据库配置适配器的债务。"""
settings_files: list[str] = []
@@ -124,6 +156,7 @@ def collect_configuration_debt_baseline() -> dict[str, Any]:
"app/plugins",
"app/sdk",
"app/runtime/compat",
"app/testing",
],
},
"settings_imports": {
@@ -144,7 +177,7 @@ def iter_import_candidates(
"""提取模块导入候选,第二项记录 from-import 的具体符号。"""
package = module_name if path.name == "__init__.py" else module_name.rpartition(".")[0]
candidates: list[tuple[str, Optional[str]]] = []
for node in ast.walk(parse_source(path)):
for node in iter_runtime_import_nodes(parse_source(path)):
if isinstance(node, ast.Import):
candidates.extend((alias.name, None) for alias in node.names)
continue
+12
View File
@@ -2383,11 +2383,23 @@ def _apply_local_system_config_inner(config_payload: dict[str, Any]) -> None:
from app.startup.database_initializer import prepare_database
from app.db.oper.systemconfig import SystemConfigOper
from app.schemas.types import SystemConfigKey
from app.db.session import SessionFactory, async_session_scope
from app.db.uow import configure_transaction_runners
from app.startup.transaction import TransactionalWriteRunner
except ModuleNotFoundError as exc:
raise RuntimeError(
"当前环境尚未安装 MoviePilot 运行依赖,请先执行 moviepilot install deps 或 moviepilot setup"
) from exc
transaction_runner = TransactionalWriteRunner(
sync_session=SessionFactory,
async_session=async_session_scope,
)
configure_transaction_runners(
sync=transaction_runner.sync,
async_=transaction_runner.async_,
)
generated_password = None
def prepare_superuser_password() -> None: