mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-03-05 17:27:42 +08:00
Replace SQLite exclusive lock with cross-platform file lock
- Use filelock (FileLock) instead of PRAGMA locking_mode=EXCLUSIVE to prevent multi-process database access. The OS automatically releases the lock when the process exits, even on crashes or Ctrl+C. - Add friendly error messages for database-is-locked and general database init failures when --enable-assets is set. - Exit the process instead of silently disabling assets when the user explicitly passed --enable-assets and the database fails. - Add filelock to requirements.txt. Amp-Thread-ID: https://ampcode.com/threads/T-019cbab8-50d4-748c-9669-2506575dda44 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
parent
d5cac66405
commit
6e33c4985a
@ -3,6 +3,7 @@ import os
|
||||
import shutil
|
||||
from app.logger import log_startup_warning
|
||||
from utils.install_util import get_missing_requirements_message
|
||||
from filelock import FileLock, Timeout
|
||||
from comfy.cli_args import args
|
||||
|
||||
_DB_AVAILABLE = False
|
||||
@ -15,7 +16,6 @@ try:
|
||||
from alembic.runtime.migration import MigrationContext
|
||||
from alembic.script import ScriptDirectory
|
||||
from sqlalchemy import create_engine, event
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
_DB_AVAILABLE = True
|
||||
@ -66,20 +66,22 @@ def get_db_path():
|
||||
raise ValueError(f"Unsupported database URL '{url}'.")
|
||||
|
||||
|
||||
def _acquire_exclusive_lock(engine, db_path):
|
||||
"""Acquire an exclusive SQLite lock to prevent multi-process access.
|
||||
_db_lock = None
|
||||
|
||||
The lock is held for the lifetime of the connection (and thus the process).
|
||||
A second process attempting to use the same database will fail fast at startup.
|
||||
def _acquire_file_lock(db_path):
|
||||
"""Acquire an OS-level file lock to prevent multi-process access.
|
||||
|
||||
Uses filelock for cross-platform support (macOS, Linux, Windows).
|
||||
The OS automatically releases the lock when the process exits, even on crashes.
|
||||
"""
|
||||
conn = engine.connect()
|
||||
global _db_lock
|
||||
lock_path = db_path + ".lock"
|
||||
_db_lock = FileLock(lock_path)
|
||||
try:
|
||||
conn.execute(sa.text("PRAGMA locking_mode=EXCLUSIVE"))
|
||||
conn.execute(sa.text("BEGIN EXCLUSIVE"))
|
||||
conn.execute(sa.text("COMMIT"))
|
||||
except Exception:
|
||||
_db_lock.acquire(timeout=0)
|
||||
except Timeout:
|
||||
raise RuntimeError(
|
||||
f"Could not acquire exclusive lock on database '{db_path}'. "
|
||||
f"Could not acquire lock on database '{db_path}'. "
|
||||
"Another ComfyUI process may already be using it. "
|
||||
"Use --database-url to specify a separate database file."
|
||||
)
|
||||
@ -132,11 +134,11 @@ def init_db():
|
||||
logging.exception("Error upgrading database: ")
|
||||
raise e
|
||||
|
||||
# Acquire an exclusive lock after migrations are complete.
|
||||
# Acquire an OS-level file lock after migrations are complete.
|
||||
# Alembic uses its own connection, so we must wait until it's done
|
||||
# before locking — otherwise our own lock blocks the migration.
|
||||
conn.close()
|
||||
_acquire_exclusive_lock(engine, db_path)
|
||||
_acquire_file_lock(db_path)
|
||||
|
||||
global Session
|
||||
Session = sessionmaker(bind=engine)
|
||||
|
||||
23
main.py
23
main.py
@ -7,7 +7,6 @@ import folder_paths
|
||||
import time
|
||||
from comfy.cli_args import args, enables_dynamic_vram
|
||||
from app.logger import setup_logger
|
||||
from app.assets.api.routes import disable_assets_routes
|
||||
from app.assets.seeder import asset_seeder
|
||||
import itertools
|
||||
import utils.extra_config
|
||||
@ -16,6 +15,7 @@ import sys
|
||||
from comfy_execution.progress import get_progress_state
|
||||
from comfy_execution.utils import get_executing_context
|
||||
from comfy_api import feature_flags
|
||||
from app.database.db import init_db, dependencies_available
|
||||
|
||||
if __name__ == "__main__":
|
||||
#NOTE: These do not do anything on core ComfyUI, they are for custom nodes.
|
||||
@ -357,17 +357,30 @@ def cleanup_temp():
|
||||
|
||||
def setup_database():
|
||||
try:
|
||||
from app.database.db import init_db, dependencies_available
|
||||
if dependencies_available():
|
||||
init_db()
|
||||
if args.enable_assets:
|
||||
if asset_seeder.start(roots=("models", "input", "output"), prune_first=True, compute_hashes=True):
|
||||
logging.info("Background asset scan initiated for models, input, output")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to initialize database. Please ensure you have installed the latest requirements. If the error persists, please report this as in future the database will be required: {e}")
|
||||
if "database is locked" in str(e):
|
||||
logging.error(
|
||||
"Database is locked. Another ComfyUI process is already using this database.\n"
|
||||
"To resolve this, specify a separate database file for this instance:\n"
|
||||
" --database-url sqlite:///path/to/another.db"
|
||||
)
|
||||
sys.exit(1)
|
||||
if args.enable_assets:
|
||||
disable_assets_routes()
|
||||
asset_seeder.disable()
|
||||
logging.error(
|
||||
f"Failed to initialize database: {e}\n"
|
||||
"The --enable-assets flag requires a working database connection.\n"
|
||||
"To resolve this, try one of the following:\n"
|
||||
" 1. Install the latest requirements: pip install -r requirements.txt\n"
|
||||
" 2. Specify an alternative database URL: --database-url sqlite:///path/to/your.db\n"
|
||||
" 3. Use an in-memory database: --database-url sqlite:///:memory:"
|
||||
)
|
||||
sys.exit(1)
|
||||
logging.error(f"Failed to initialize database. Please ensure you have installed the latest requirements. If the error persists, please report this as in future the database will be required: {e}")
|
||||
|
||||
|
||||
def start_comfyui(asyncio_loop=None):
|
||||
|
||||
@ -20,6 +20,7 @@ tqdm
|
||||
psutil
|
||||
alembic
|
||||
SQLAlchemy
|
||||
filelock
|
||||
av>=14.2.0
|
||||
comfy-kitchen>=0.2.7
|
||||
comfy-aimdo>=0.2.4
|
||||
|
||||
Loading…
Reference in New Issue
Block a user