Skip to content

Commit 78580b7

Browse files
committed
Fix migrate on empty?
1 parent 9026d95 commit 78580b7

1 file changed

Lines changed: 44 additions & 47 deletions

File tree

biomero/db_migrate.py

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
2-
import pathlib
32
import logging
3+
import pathlib
44
from alembic import command
55
from alembic.config import Config
66
from sqlalchemy import create_engine, inspect, text
@@ -10,58 +10,54 @@
1010

1111

1212
def _mask_url(url: str) -> str:
13-
"""Mask password in a SQLAlchemy URL for safe logging."""
1413
try:
15-
if not url or '://' not in url:
16-
return url
17-
scheme, rest = url.split('://', 1)
18-
if '@' not in rest:
19-
return url
20-
creds, tail = rest.split('@', 1)
21-
if ':' not in creds:
22-
return url
23-
user, _ = creds.split(':', 1)
24-
return f"{scheme}://{user}:******@{tail}"
14+
# Basic masking: replace password between ://user:pass@ with ******
15+
if '://' in url and '@' in url and ':' in url.split('://', 1)[1]:
16+
scheme, rest = url.split('://', 1)
17+
creds, tail = rest.split('@', 1)
18+
if ':' in creds:
19+
user, _ = creds.split(':', 1)
20+
return f"{scheme}://{user}:******@{tail}"
2521
except Exception:
26-
return url
22+
pass
23+
return url
2724

2825

2926
def run_migrations_on_startup():
30-
"""
31-
Programmatic migration runner for BIOMERO.
32-
33-
Controlled by env:
34-
- BIOMERO_RUN_MIGRATIONS=1 to enable (default 1)
35-
- SQLALCHEMY_URL for DB connection string
36-
- BIOMERO_ALLOW_AUTO_STAMP=1 to adopt existing schema by stamping head
37-
"""
3827
if os.getenv("BIOMERO_RUN_MIGRATIONS", "1") != "1":
3928
return
4029

41-
logger = logging.getLogger(__name__)
42-
4330
# Prefer the DB URL from EngineManager (engine already created).
4431
db_url = None
4532
try:
4633
from .database import EngineManager
4734
if getattr(EngineManager, "_engine", None):
48-
# Stringify without exposing password
4935
db_url = str(EngineManager._engine.url)
5036
except Exception:
5137
pass
52-
53-
# Fallback to env var if needed
38+
# Fallback to env vars if tracker not available
5439
if not db_url:
5540
db_url = os.getenv("SQLALCHEMY_URL")
5641
if not db_url:
5742
raise RuntimeError(
58-
"BIOMERO migrations: No DB URL. Ensure EngineManager is "
43+
"BIOMERO migrations: No DB URL found. Ensure EngineManager is "
5944
"initialized or set SQLALCHEMY_URL."
6045
)
6146

47+
logger = logging.getLogger(__name__)
6248
logger.info(f"BIOMERO Alembic DB: {_mask_url(db_url)}")
63-
64-
engine = create_engine(db_url)
49+
50+
# Try to reuse existing engine if available to avoid connection issues
51+
engine = None
52+
try:
53+
from .database import EngineManager
54+
if getattr(EngineManager, "_engine", None):
55+
engine = EngineManager._engine
56+
except Exception:
57+
pass
58+
59+
if engine is None:
60+
engine = create_engine(db_url)
6561

6662
cfg = Config()
6763
cfg.set_main_option("script_location", MIGRATIONS_DIR)
@@ -70,9 +66,17 @@ def run_migrations_on_startup():
7066

7167
insp = inspect(engine)
7268
has_version_table = insp.has_table(VERSION_TABLE)
69+
# Allow auto-stamp if explicitly enabled OR if tables were just created
70+
# in this process (fresh install detected by Base.metadata.after_create).
7371
allow_stamp = os.getenv("BIOMERO_ALLOW_AUTO_STAMP", "0") == "1"
74-
created_any_tables = os.getenv("BIOMERO_CREATED_ANY_TABLES", "0") == "1"
72+
try:
73+
from .database import CREATED_ANY_TABLES
74+
allow_stamp = allow_stamp or CREATED_ANY_TABLES
75+
except Exception:
76+
pass
7577

78+
# Postgres advisory lock to prevent concurrent migrations
79+
# from multiple replicas
7680
is_pg = engine.dialect.name == "postgresql"
7781

7882
with engine.begin() as conn:
@@ -84,23 +88,16 @@ def run_migrations_on_startup():
8488
)
8589
)
8690
try:
87-
# Auto-stamp scenarios:
88-
# 1) Fresh install: our process just created tables ->
89-
# stamp unconditionally.
90-
# 2) Adoption: admin allowed stamping and existing known tables
91-
# are present.
92-
if not has_version_table:
93-
if created_any_tables:
94-
command.stamp(cfg, "head")
95-
elif allow_stamp:
96-
known_tables = {
97-
"biomero_job_view",
98-
"biomero_job_progress_view",
99-
"biomero_workflow_progress_view",
100-
"biomero_task_execution",
101-
}
102-
if any(insp.has_table(t) for t in known_tables):
103-
command.stamp(cfg, "head")
91+
if allow_stamp and not has_version_table:
92+
# Check if any BIOMERO table already exists (reliable table name)
93+
known_tables = {
94+
"biomero_job_view",
95+
"biomero_job_progress_view",
96+
"biomero_workflow_progress_view",
97+
"biomero_task_execution"
98+
}
99+
if any(insp.has_table(t) for t in known_tables):
100+
command.stamp(cfg, "head") # baseline existing DB
104101
command.upgrade(cfg, "head")
105102
finally:
106103
if is_pg:

0 commit comments

Comments
 (0)