fix: acquire exclusive SQLite lock at startup to prevent multi-process DB conflicts

When two ComfyUI processes share the same database file but point to
different input/output/model directories, each process's scan marks
the other's assets as missing, causing unreliable asset visibility.
This adds an exclusive lock so the second process fails fast at startup
with a clear message to use --database-url.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Luke Mino-Altherr 2026-03-03 17:30:30 -08:00
parent 67c4f79c22
commit d638d81d6c

View File

@ -15,6 +15,7 @@ try:
from alembic.runtime.migration import MigrationContext from alembic.runtime.migration import MigrationContext
from alembic.script import ScriptDirectory from alembic.script import ScriptDirectory
from sqlalchemy import create_engine, event from sqlalchemy import create_engine, event
import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
_DB_AVAILABLE = True _DB_AVAILABLE = True
@ -76,13 +77,25 @@ def init_db():
# Check if we need to upgrade # Check if we need to upgrade
engine = create_engine(db_url) engine = create_engine(db_url)
# Enable foreign key enforcement for SQLite # Enable foreign key enforcement and exclusive locking for SQLite
@event.listens_for(engine, "connect") @event.listens_for(engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record): def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor() cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON") cursor.execute("PRAGMA foreign_keys=ON")
cursor.execute("PRAGMA locking_mode=EXCLUSIVE")
cursor.close() cursor.close()
# Acquire the exclusive lock early by opening a connection and triggering a read.
# This prevents two processes from sharing the same database file.
conn = engine.connect() conn = engine.connect()
try:
conn.execute(sa.text("PRAGMA schema_version"))
except Exception:
raise RuntimeError(
f"Could not acquire exclusive lock on database '{db_path}'. "
"Another ComfyUI process may already be using it. "
"Use --database-url to specify a separate database file."
)
context = MigrationContext.configure(conn) context = MigrationContext.configure(conn)
current_rev = context.get_current_revision() current_rev = context.get_current_revision()