Skip to content

Commit 233bd2e

Browse files
authored
feat: run db migrations offline (optionally) (#114)
* feat: run db migrations offline (optionally) * fix
1 parent b3becb6 commit 233bd2e

File tree

7 files changed

+360
-71
lines changed

7 files changed

+360
-71
lines changed

hindsight-api/hindsight_api/admin/cli.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,36 @@ def restore(
214214
typer.echo("Restore complete")
215215

216216

217+
async def _run_migration(db_url: str, schema: str = "public") -> None:
218+
"""Resolve database URL and run migrations."""
219+
from ..migrations import run_migrations
220+
221+
is_pg0, instance_name, _ = parse_pg0_url(db_url)
222+
if is_pg0:
223+
typer.echo(f"Starting embedded PostgreSQL (instance: {instance_name})...")
224+
resolved_url = await resolve_database_url(db_url)
225+
run_migrations(resolved_url, schema=schema)
226+
227+
228+
@app.command(name="run-db-migration")
229+
def run_db_migration(
230+
schema: str = typer.Option("public", "--schema", "-s", help="Database schema to run migrations on"),
231+
):
232+
"""Run database migrations to the latest version."""
233+
config = HindsightConfig.from_env()
234+
235+
if not config.database_url:
236+
typer.echo("Error: Database URL not configured.", err=True)
237+
typer.echo("Set HINDSIGHT_API_DATABASE_URL environment variable.", err=True)
238+
raise typer.Exit(1)
239+
240+
typer.echo(f"Running database migrations (schema: {schema})...")
241+
242+
asyncio.run(_run_migration(config.database_url, schema))
243+
244+
typer.echo("Database migrations completed successfully")
245+
246+
217247
def main():
218248
app()
219249

hindsight-api/hindsight_api/config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
ENV_SKIP_LLM_VERIFICATION = "HINDSIGHT_API_SKIP_LLM_VERIFICATION"
5555
ENV_LAZY_RERANKER = "HINDSIGHT_API_LAZY_RERANKER"
5656

57+
# Database migrations
58+
ENV_RUN_MIGRATIONS_ON_STARTUP = "HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP"
59+
5760
# Default values
5861
DEFAULT_DATABASE_URL = "pg0"
5962
DEFAULT_LLM_PROVIDER = "openai"
@@ -83,6 +86,9 @@
8386
# Retain settings
8487
DEFAULT_RETAIN_MAX_COMPLETION_TOKENS = 64000 # Max tokens for fact extraction LLM call
8588

89+
# Database migrations
90+
DEFAULT_RUN_MIGRATIONS_ON_STARTUP = True
91+
8692
# Default MCP tool descriptions (can be customized via env vars)
8793
DEFAULT_MCP_RETAIN_DESCRIPTION = """Store important information to long-term memory.
8894
@@ -152,6 +158,9 @@ class HindsightConfig:
152158
skip_llm_verification: bool
153159
lazy_reranker: bool
154160

161+
# Database migrations
162+
run_migrations_on_startup: bool
163+
155164
@classmethod
156165
def from_env(cls) -> "HindsightConfig":
157166
"""Create configuration from environment variables."""
@@ -192,6 +201,8 @@ def from_env(cls) -> "HindsightConfig":
192201
retain_max_completion_tokens=int(
193202
os.getenv(ENV_RETAIN_MAX_COMPLETION_TOKENS, str(DEFAULT_RETAIN_MAX_COMPLETION_TOKENS))
194203
),
204+
# Database migrations
205+
run_migrations_on_startup=os.getenv(ENV_RUN_MIGRATIONS_ON_STARTUP, "true").lower() == "true",
195206
)
196207

197208
def get_llm_base_url(self) -> str:

hindsight-api/hindsight_api/main.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ def release_lock():
187187
retain_max_completion_tokens=config.retain_max_completion_tokens,
188188
skip_llm_verification=config.skip_llm_verification,
189189
lazy_reranker=config.lazy_reranker,
190+
run_migrations_on_startup=config.run_migrations_on_startup,
190191
)
191192
config.configure_logging()
192193
if not args.daemon:
@@ -212,7 +213,11 @@ def release_lock():
212213
logging.info(f"Loaded tenant extension: {tenant_extension.__class__.__name__}")
213214

214215
# Create MemoryEngine (reads configuration from environment)
215-
_memory = MemoryEngine(operation_validator=operation_validator, tenant_extension=tenant_extension)
216+
_memory = MemoryEngine(
217+
operation_validator=operation_validator,
218+
tenant_extension=tenant_extension,
219+
run_migrations=config.run_migrations_on_startup,
220+
)
216221

217222
# Set extension context on tenant extension (needed for schema provisioning)
218223
if tenant_extension:

0 commit comments

Comments
 (0)