|
1 | 1 | """Database management commands.""" |
2 | 2 |
|
| 3 | +# PEP 563 lazy annotations let signatures reference IndexProgress without importing |
| 4 | +# the indexing stack at module load; reset/reindex import their heavy database and |
| 5 | +# sync dependencies at call time so CLI startup stays fast (#886). |
| 6 | +from __future__ import annotations |
| 7 | + |
3 | 8 | import os |
4 | 9 | from dataclasses import dataclass |
5 | 10 | from pathlib import Path, PurePosixPath, PureWindowsPath |
| 11 | +from typing import TYPE_CHECKING |
6 | 12 |
|
7 | 13 | import psutil |
8 | 14 | import typer |
9 | 15 | from loguru import logger |
10 | 16 | from rich.console import Console |
11 | 17 | from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn |
12 | | -from sqlalchemy.exc import OperationalError |
13 | 18 |
|
14 | | -from basic_memory import db |
15 | 19 | from basic_memory.cli.app import app |
16 | 20 | from basic_memory.cli.commands.command_utils import run_with_cleanup |
17 | 21 | from basic_memory.config import ConfigManager, ProjectMode |
18 | | -from basic_memory.indexing import IndexProgress |
19 | | -from basic_memory.repository import ProjectRepository |
20 | | -from basic_memory.services.initialization import reconcile_projects_with_config |
21 | | -from basic_memory.sync.sync_service import get_sync_service |
| 22 | + |
| 23 | +if TYPE_CHECKING: |
| 24 | + from basic_memory.indexing import IndexProgress |
22 | 25 |
|
23 | 26 | console = Console() |
24 | 27 |
|
@@ -159,6 +162,13 @@ async def _reindex_projects(app_config): |
159 | 162 | This ensures all database operations use the same event loop, |
160 | 163 | and proper cleanup happens when the function completes. |
161 | 164 | """ |
| 165 | + # Deferred: SQLAlchemy, repositories, and the sync stack load only when a |
| 166 | + # reindex actually runs, not on every CLI start (#886). |
| 167 | + from basic_memory import db |
| 168 | + from basic_memory.repository import ProjectRepository |
| 169 | + from basic_memory.services.initialization import reconcile_projects_with_config |
| 170 | + from basic_memory.sync.sync_service import get_sync_service |
| 171 | + |
162 | 172 | try: |
163 | 173 | await reconcile_projects_with_config(app_config) |
164 | 174 |
|
@@ -197,6 +207,12 @@ def reset( |
197 | 207 | ), |
198 | 208 | ): # pragma: no cover |
199 | 209 | """Reset database (drop all tables and recreate).""" |
| 210 | + # Deferred: SQLAlchemy and the db module load only when a reset actually |
| 211 | + # runs, not on every CLI start (#886). |
| 212 | + from sqlalchemy.exc import OperationalError |
| 213 | + |
| 214 | + from basic_memory import db |
| 215 | + |
200 | 216 | console.print( |
201 | 217 | "[yellow]Note:[/yellow] This only deletes the index database. " |
202 | 218 | "Your markdown note files will not be affected.\n" |
@@ -320,10 +336,15 @@ async def _reindex( |
320 | 336 | project: str | None, |
321 | 337 | ): |
322 | 338 | """Run reindex operations.""" |
323 | | - from basic_memory.repository import EntityRepository |
| 339 | + # Deferred: SQLAlchemy, repositories, and the sync stack load only when a |
| 340 | + # reindex actually runs, not on every CLI start (#886). |
| 341 | + from basic_memory import db |
| 342 | + from basic_memory.repository import EntityRepository, ProjectRepository |
324 | 343 | from basic_memory.repository.search_repository import create_search_repository |
| 344 | + from basic_memory.services.initialization import reconcile_projects_with_config |
325 | 345 | from basic_memory.services.search_service import SearchService |
326 | 346 | from basic_memory.services.file_service import FileService |
| 347 | + from basic_memory.sync.sync_service import get_sync_service |
327 | 348 | from basic_memory.markdown.markdown_processor import MarkdownProcessor |
328 | 349 | from basic_memory.markdown.entity_parser import EntityParser |
329 | 350 |
|
|
0 commit comments