代码修改

This commit is contained in:
吉鑫升 committed 2026-05-21 20:19:44 +08:00
1 parent 843eda6fea
commit ac4424bab2
3 files changed
+41 -3

No files matched your search

+1 -1
View File
@@ -154,7 +154,7 @@ memory:
hindsight: # provider=hindsight 时生效,需另行部署 Hindsight 服务
mode: local_external # 'cloud' | 'local_embedded' | 'local_external'
api_url: http://localhost:8765
api_url: http://47.88.25.99:18888
api_key: "" # 部署 Hindsight 后填,或改成 $HINDSIGHT_API_KEY 并设同名环境变量
# 注意:写成 $VAR 但环境变量未设置会导致配置加载失败
bank_id_template: "deerflow-user-{user_id}"
@@ -13,6 +13,7 @@ from __future__ import annotations
import asyncio
import json
import logging
import os
import sys
from importlib.util import find_spec
from pathlib import Path
@@ -77,6 +78,10 @@ async def _run_alembic_upgrade(url: str) -> None:
operable on the ``create_all`` schema; the operator just won't get
in-place fixes until they investigate.
"""
if os.getenv("DEER_FLOW_SKIP_ALEMBIC", "").lower() in ("1", "true", "yes"):
logger.warning("DEER_FLOW_SKIP_ALEMBIC is set; skipping Alembic migrations (schema stays at create_all)")
return
ini_path = Path(__file__).parent / "migrations" / "alembic.ini"
if not ini_path.exists():
logger.warning("Alembic config not found at %s; skipping auto-migrate", ini_path)
@@ -102,9 +107,26 @@ async def _run_alembic_upgrade(url: str) -> None:
# at the directory of alembic.ini itself — already correct for us.
command.upgrade(cfg, "head")
# Bound the upgrade so a stuck DDL (e.g. MySQL metadata-lock wait) cannot
# hang startup forever. Tunable via DEER_FLOW_ALEMBIC_TIMEOUT (seconds).
# NOTE: asyncio.wait_for cancels the *await* on timeout; the worker thread
# itself keeps running (Python can't kill threads). That's acceptable —
# the orphan thread will exit when its MySQL connection eventually errors
# or when the process restarts. The point here is to unblock startup.
try:
await asyncio.to_thread(_do_upgrade)
timeout_s = float(os.getenv("DEER_FLOW_ALEMBIC_TIMEOUT", "60"))
except ValueError:
timeout_s = 60.0
try:
await asyncio.wait_for(asyncio.to_thread(_do_upgrade), timeout=timeout_s)
logger.info("Alembic migrations applied (or already up-to-date)")
except asyncio.TimeoutError:
logger.error(
"Alembic upgrade did not finish within %.0fs; continuing startup on create_all schema. "
"Likely cause: MySQL metadata-lock wait — check SHOW FULL PROCESSLIST for a blocking transaction.",
timeout_s,
)
except Exception:
logger.exception("Auto-applying Alembic migrations failed; continuing with create_all schema")
@@ -257,7 +279,7 @@ async def init_engine(
# Apply in-place schema fixes (column widenings, etc.) that ``create_all``
# cannot do on its own. Failures don't abort startup — see the helper.
await _run_alembic_upgrade(url)
# await _run_alembic_upgrade(url)
logger.info("Persistence engine initialized: backend=%s", backend)
@@ -9,9 +9,11 @@ from __future__ import annotations
import asyncio
import logging
import os
from logging.config import fileConfig
from alembic import context
from sqlalchemy import text
from sqlalchemy.ext.asyncio import create_async_engine
from deerflow.persistence.base import Base
@@ -46,6 +48,20 @@ def run_migrations_offline() -> None:
def do_run_migrations(connection):
render_as_batch = connection.dialect.name == "sqlite"
# On MySQL, shrink the session lock waits so a blocked DDL fails fast
# instead of hanging on the server default (lock_wait_timeout = 31536000s
# = 1 year; innodb_lock_wait_timeout = 50s). Without this, an idle
# transaction on another connection can freeze startup indefinitely.
# Tunable via DEER_FLOW_ALEMBIC_LOCK_WAIT (seconds, default 15).
if connection.dialect.name == "mysql":
try:
lock_wait = int(os.getenv("DEER_FLOW_ALEMBIC_LOCK_WAIT", "15"))
except ValueError:
lock_wait = 15
connection.execute(text(f"SET SESSION lock_wait_timeout = {lock_wait}"))
connection.execute(text(f"SET SESSION innodb_lock_wait_timeout = {lock_wait}"))
context.configure(
connection=connection,
target_metadata=target_metadata,