This commit is contained in:
Constantine 2026-07-19 19:40:24 -07:00 committed by GitHub
commit e6cc18a86b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 165 additions and 6 deletions

View File

@ -4,7 +4,7 @@ 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
from comfy.cli_args import args, database_default_path
_DB_AVAILABLE = False
Session = None
@ -57,19 +57,62 @@ def get_alembic_config():
config = Config(config_path)
config.set_main_option("script_location", scripts_path)
config.set_main_option("sqlalchemy.url", args.database_url)
config.set_main_option("sqlalchemy.url", get_database_url())
return config
def get_database_url():
if args.database_url is not None:
return args.database_url
import folder_paths
db_path = os.path.join(folder_paths.get_user_directory(), "comfyui.db")
return f"sqlite:///{db_path}"
def get_legacy_default_db_path():
return database_default_path
def get_db_path():
url = args.database_url
url = get_database_url()
if url.startswith("sqlite:///"):
return url.split("///")[1]
return url.split("///", 1)[1]
else:
raise ValueError(f"Unsupported database URL '{url}'.")
def copy_legacy_default_db(db_path):
if args.database_url is not None:
return
legacy_db_path = get_legacy_default_db_path()
if legacy_db_path is None:
return
if os.path.abspath(legacy_db_path) == os.path.abspath(db_path):
return
if os.path.exists(db_path) or not os.path.exists(legacy_db_path):
return
shutil.copy(legacy_db_path, db_path)
os.replace(legacy_db_path, legacy_db_path + ".bak")
logging.info(
f"Copied legacy database from '{legacy_db_path}' to '{db_path}' and renamed the original to '{legacy_db_path}.bak'"
)
def prepare_file_db_path(db_path):
db_dir = os.path.dirname(db_path)
if db_dir:
os.makedirs(db_dir, exist_ok=True)
copy_legacy_default_db(db_path)
_db_lock = None
def _acquire_file_lock(db_path):
@ -97,7 +140,7 @@ def _is_memory_db(db_url):
def init_db():
db_url = args.database_url
db_url = get_database_url()
logging.debug(f"Database URL: {db_url}")
if _is_memory_db(db_url):
@ -134,6 +177,7 @@ def _init_memory_db(db_url):
def _init_file_db(db_url):
"""Initialize a file-backed SQLite database using Alembic migrations."""
db_path = get_db_path()
prepare_file_db_path(db_path)
db_exists = os.path.exists(db_path)
config = get_alembic_config()

View File

@ -240,7 +240,7 @@ parser.add_argument(
database_default_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "user", "comfyui.db")
)
parser.add_argument("--database-url", type=str, default=f"sqlite:///{database_default_path}", help="Specify the database URL, e.g. for an in-memory database you can use 'sqlite:///:memory:'.")
parser.add_argument("--database-url", type=str, default=None, help="Specify the database URL, e.g. for an in-memory database you can use 'sqlite:///:memory:'. Defaults to 'comfyui.db' in the effective user directory.")
parser.add_argument("--enable-assets", action="store_true", help="Enable the assets system (API routes, database synchronization, and background scanning).")
parser.add_argument("--enable-asset-hashing", action="store_true", help="Compute blake3 content hashes when scanning assets. Hashing enables future asset-portability features (deduplication, cross-machine model resolution) but adds startup cost and per-output cost on large models directories. Off by default; enable to opt in.")
parser.add_argument("--feature-flag", type=str, action='append', default=[], metavar="KEY[=VALUE]", help="Set a server feature flag. Use KEY=VALUE to set an explicit value, or bare KEY to set it to true. Can be specified multiple times. Boolean values (true/false) and numbers are auto-converted. Examples: --feature-flag show_signin_button=true or --feature-flag show_signin_button")

View File

@ -0,0 +1,115 @@
import os
from app.database import db
from comfy.cli_args import database_default_path
def test_default_database_url_uses_effective_user_directory(monkeypatch, tmp_path):
user_dir = tmp_path / "custom_user"
user_dir.mkdir()
monkeypatch.setattr(db.args, "database_url", None)
monkeypatch.setattr("folder_paths.get_user_directory", lambda: str(user_dir))
assert db.get_database_url() == f"sqlite:///{user_dir / 'comfyui.db'}"
def test_default_db_path_matches_legacy_default_without_custom_user_directory(monkeypatch):
import folder_paths
monkeypatch.setattr(db.args, "database_url", None)
monkeypatch.setattr(
"folder_paths.get_user_directory",
lambda: os.path.join(folder_paths.base_path, "user"),
)
assert os.path.abspath(db.get_db_path()) == database_default_path
def test_explicit_database_url_is_preserved(monkeypatch):
database_url = "sqlite:///:memory:"
monkeypatch.setattr(db.args, "database_url", database_url)
assert db.get_database_url() == database_url
def test_explicit_url_at_legacy_default_location_is_honoured(monkeypatch):
url = f"sqlite:///{database_default_path}"
monkeypatch.setattr(db.args, "database_url", url)
assert db.get_database_url() == url
assert db.get_db_path() == database_default_path
def test_explicit_database_url_skips_legacy_copy(monkeypatch, tmp_path):
legacy_db = tmp_path / "install" / "user" / "comfyui.db"
target_db = tmp_path / "target" / "comfyui.db"
legacy_db.parent.mkdir(parents=True)
target_db.parent.mkdir(parents=True)
legacy_db.write_bytes(b"legacy db")
monkeypatch.setattr(db.args, "database_url", f"sqlite:///{target_db}")
monkeypatch.setattr(db, "get_legacy_default_db_path", lambda: str(legacy_db))
db.copy_legacy_default_db(str(target_db))
assert not target_db.exists()
def test_legacy_default_database_is_copied_to_effective_user_directory(monkeypatch, tmp_path):
legacy_db = tmp_path / "install" / "user" / "comfyui.db"
user_dir = tmp_path / "custom_user"
legacy_db.parent.mkdir(parents=True)
user_dir.mkdir()
legacy_db.write_bytes(b"legacy db")
monkeypatch.setattr(db.args, "database_url", None)
monkeypatch.setattr("folder_paths.get_user_directory", lambda: str(user_dir))
monkeypatch.setattr(db, "get_legacy_default_db_path", lambda: str(legacy_db))
db.copy_legacy_default_db(str(user_dir / "comfyui.db"))
assert (user_dir / "comfyui.db").read_bytes() == b"legacy db"
assert not legacy_db.exists()
assert legacy_db.with_suffix(".db.bak").read_bytes() == b"legacy db"
def test_legacy_default_database_does_not_overwrite_existing_effective_db(monkeypatch, tmp_path):
legacy_db = tmp_path / "install" / "user" / "comfyui.db"
user_db = tmp_path / "custom_user" / "comfyui.db"
legacy_db.parent.mkdir(parents=True)
user_db.parent.mkdir(parents=True)
legacy_db.write_bytes(b"legacy db")
user_db.write_bytes(b"user db")
monkeypatch.setattr(db.args, "database_url", None)
monkeypatch.setattr(db, "get_legacy_default_db_path", lambda: str(legacy_db))
db.copy_legacy_default_db(str(user_db))
assert user_db.read_bytes() == b"user db"
assert legacy_db.read_bytes() == b"legacy db"
def test_prepare_file_database_creates_parent_directory(monkeypatch, tmp_path):
db_path = tmp_path / "nested" / "comfyui.db"
monkeypatch.setattr(db.args, "database_url", None)
monkeypatch.setattr(db, "copy_legacy_default_db", lambda path: None)
db.prepare_file_db_path(str(db_path))
assert db_path.parent.is_dir()
def test_prepare_file_database_accepts_relative_database_path(monkeypatch, tmp_path):
monkeypatch.chdir(tmp_path)
monkeypatch.setattr(db.args, "database_url", "sqlite:///relative.db")
monkeypatch.setattr(db, "copy_legacy_default_db", lambda path: None)
db.prepare_file_db_path("relative.db")
assert os.getcwd() == str(tmp_path)
assert not list(tmp_path.iterdir())