代码修改
This commit is contained in:
1 parent
843eda6fea
commit
ac4424bab2
3 files changed
+48
-10
No files matched your search
@@ -154,7 +154,7 @@ memory:
|
|||||||
|
|
||||||
hindsight: # provider=hindsight 时生效,需另行部署 Hindsight 服务
|
hindsight: # provider=hindsight 时生效,需另行部署 Hindsight 服务
|
||||||
mode: local_external # 'cloud' | 'local_embedded' | 'local_external'
|
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 并设同名环境变量
|
api_key: "" # 部署 Hindsight 后填,或改成 $HINDSIGHT_API_KEY 并设同名环境变量
|
||||||
# 注意:写成 $VAR 但环境变量未设置会导致配置加载失败
|
# 注意:写成 $VAR 但环境变量未设置会导致配置加载失败
|
||||||
bank_id_template: "deerflow-user-{user_id}"
|
bank_id_template: "deerflow-user-{user_id}"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from __future__ import annotations
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from importlib.util import find_spec
|
from importlib.util import find_spec
|
||||||
from pathlib import Path
|
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
|
operable on the ``create_all`` schema; the operator just won't get
|
||||||
in-place fixes until they investigate.
|
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"
|
ini_path = Path(__file__).parent / "migrations" / "alembic.ini"
|
||||||
if not ini_path.exists():
|
if not ini_path.exists():
|
||||||
logger.warning("Alembic config not found at %s; skipping auto-migrate", ini_path)
|
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.
|
# at the directory of alembic.ini itself — already correct for us.
|
||||||
command.upgrade(cfg, "head")
|
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:
|
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)")
|
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:
|
except Exception:
|
||||||
logger.exception("Auto-applying Alembic migrations failed; continuing with create_all schema")
|
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``
|
# Apply in-place schema fixes (column widenings, etc.) that ``create_all``
|
||||||
# cannot do on its own. Failures don't abort startup — see the helper.
|
# 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)
|
logger.info("Persistence engine initialized: backend=%s", backend)
|
||||||
|
|
||||||
|
|||||||
+23
-7
@@ -9,9 +9,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
|
|
||||||
from alembic import context
|
from alembic import context
|
||||||
|
from sqlalchemy import text
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine
|
from sqlalchemy.ext.asyncio import create_async_engine
|
||||||
|
|
||||||
from deerflow.persistence.base import Base
|
from deerflow.persistence.base import Base
|
||||||
@@ -44,13 +46,27 @@ def run_migrations_offline() -> None:
|
|||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
def do_run_migrations(connection):
|
def do_run_migrations(connection):
|
||||||
render_as_batch = connection.dialect.name == "sqlite"
|
render_as_batch = connection.dialect.name == "sqlite"
|
||||||
context.configure(
|
|
||||||
connection=connection,
|
# On MySQL, shrink the session lock waits so a blocked DDL fails fast
|
||||||
target_metadata=target_metadata,
|
# instead of hanging on the server default (lock_wait_timeout = 31536000s
|
||||||
render_as_batch=render_as_batch, # Required for SQLite ALTER TABLE support
|
# = 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,
|
||||||
|
render_as_batch=render_as_batch, # Required for SQLite ALTER TABLE support
|
||||||
|
)
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user