Skip to content

Commit 48a2e29

Browse files
jsbattigclaude
andcommitted
fix: Standardize SQLite backend usage across all entity managers (Story #702)
Multiple entity managers were not using SQLite despite having backends available: 1. CITokenManager in routes.py - Fixed wrong DB path (cidx.db → cidx_server.db) 2. CITokenManager in git_state_manager.py - Added use_sqlite=True 3. SSHKeyManager - Created factory functions with SQLite in: - web/routes.py (5 locations) - routers/ssh_keys.py - mcp/handlers.py - services/committer_resolution_service.py - services/migration_orchestrator.py 4. SyncJobManager - Updated create_sync_job_manager() factory All managers now consistently use ~/.cidx-server/data/cidx_server.db Added unit tests for SQLite factory functions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 81374af commit 48a2e29

9 files changed

Lines changed: 382 additions & 36 deletions

File tree

src/code_indexer/server/jobs/manager.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,7 +2311,7 @@ def update_phase_details(
23112311

23122312
def create_sync_job_manager(server_dir_path: Optional[str] = None) -> SyncJobManager:
23132313
"""
2314-
Create a properly configured SyncJobManager.
2314+
Create a properly configured SyncJobManager with SQLite backend (Story #702).
23152315
23162316
Factory function that creates a SyncJobManager with appropriate
23172317
storage configuration based on CIDX server settings.
@@ -2328,4 +2328,13 @@ def create_sync_job_manager(server_dir_path: Optional[str] = None) -> SyncJobMan
23282328
storage_path = config.get_jobs_storage_path()
23292329
concurrency_config = config.get_concurrency_limits()
23302330

2331-
return SyncJobManager(storage_path=storage_path, **concurrency_config)
2331+
# Calculate database path for SQLite backend
2332+
server_dir = Path(server_dir_path or "~/.cidx-server").expanduser()
2333+
db_path = str(server_dir / "data" / "cidx_server.db")
2334+
2335+
return SyncJobManager(
2336+
storage_path=storage_path,
2337+
use_sqlite=True,
2338+
db_path=db_path,
2339+
**concurrency_config,
2340+
)

src/code_indexer/server/mcp/handlers.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4004,10 +4004,21 @@ async def handle_authenticate(
40044004

40054005

40064006
def get_ssh_key_manager() -> SSHKeyManager:
4007-
"""Get or create the SSH key manager instance."""
4007+
"""Get or create the SSH key manager instance with SQLite backend (Story #702)."""
40084008
global _ssh_key_manager
40094009
if _ssh_key_manager is None:
4010-
_ssh_key_manager = SSHKeyManager()
4010+
from ..services.config_service import get_config_service
4011+
4012+
config_service = get_config_service()
4013+
server_dir = config_service.config_manager.server_dir
4014+
db_path = server_dir / "data" / "cidx_server.db"
4015+
metadata_dir = server_dir / "data" / "ssh_keys"
4016+
4017+
_ssh_key_manager = SSHKeyManager(
4018+
metadata_dir=metadata_dir,
4019+
use_sqlite=True,
4020+
db_path=db_path,
4021+
)
40114022
return _ssh_key_manager
40124023

40134024

src/code_indexer/server/routers/ssh_keys.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,31 @@ class KeyWithHostsResponse(BaseModel):
9999

100100

101101
def get_ssh_key_manager() -> SSHKeyManager:
102-
"""Get or create the SSH key manager instance."""
102+
"""Get or create the SSH key manager instance with SQLite backend (Story #702)."""
103103
global _ssh_key_manager
104104
if _ssh_key_manager is None:
105105
# Allow override via environment variables for testing
106106
ssh_dir = os.environ.get("CIDX_SSH_DIR")
107107
metadata_dir_env = os.environ.get("CIDX_SSH_METADATA_DIR")
108-
server_data_dir = os.environ.get(
109-
"CIDX_SERVER_DATA_DIR", str(Path.home() / ".code-indexer-server")
110-
)
108+
109+
# Get server directory from config service
110+
from ..services.config_service import get_config_service
111+
112+
config_service = get_config_service()
113+
server_dir = config_service.config_manager.server_dir
114+
db_path = server_dir / "data" / "cidx_server.db"
111115

112116
# Use server data dir for metadata if not explicitly overridden
113117
if metadata_dir_env:
114118
metadata_dir = Path(metadata_dir_env)
115119
else:
116-
metadata_dir = Path(server_data_dir) / "ssh_keys"
120+
metadata_dir = server_dir / "data" / "ssh_keys"
117121

118122
_ssh_key_manager = SSHKeyManager(
119123
ssh_dir=Path(ssh_dir) if ssh_dir else None,
120124
metadata_dir=metadata_dir,
125+
use_sqlite=True,
126+
db_path=db_path,
121127
)
122128
return _ssh_key_manager
123129

src/code_indexer/server/services/committer_resolution_service.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
from .remote_discovery_service import RemoteDiscoveryService
1717

1818

19+
def _create_default_ssh_key_manager() -> SSHKeyManager:
20+
"""Create SSHKeyManager with SQLite backend (Story #702 migration)."""
21+
from .config_service import get_config_service
22+
23+
config_service = get_config_service()
24+
server_dir = config_service.config_manager.server_dir
25+
db_path = server_dir / "data" / "cidx_server.db"
26+
metadata_dir = server_dir / "data" / "ssh_keys"
27+
28+
return SSHKeyManager(
29+
metadata_dir=metadata_dir,
30+
use_sqlite=True,
31+
db_path=db_path,
32+
)
33+
34+
1935
class CommitterResolutionService:
2036
"""
2137
Service for resolving git committer email based on SSH key authentication.
@@ -44,7 +60,7 @@ def __init__(
4460
self.logger = logging.getLogger(__name__)
4561

4662
# Initialize dependencies with defaults if not provided
47-
self.ssh_key_manager = ssh_key_manager or SSHKeyManager()
63+
self.ssh_key_manager = ssh_key_manager or _create_default_ssh_key_manager()
4864
self.key_to_remote_tester = key_to_remote_tester or KeyToRemoteTester()
4965
self.remote_discovery_service = (
5066
remote_discovery_service or RemoteDiscoveryService()

src/code_indexer/server/services/git_state_manager.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,16 @@ def resolve_token(platform: str) -> Optional[str]:
582582
from .ci_token_manager import CITokenManager
583583

584584
server_dir = Path.home() / ".cidx-server"
585-
token_manager = CITokenManager(server_dir_path=str(server_dir))
585+
db_path = server_dir / "data" / "cidx_server.db"
586+
587+
# Ensure database directory exists before opening SQLite
588+
db_path.parent.mkdir(parents=True, exist_ok=True)
589+
590+
token_manager = CITokenManager(
591+
server_dir_path=str(server_dir),
592+
use_sqlite=True,
593+
db_path=str(db_path),
594+
)
586595
token_data = token_manager.get_token(platform)
587596

588597
if token_data:

src/code_indexer/server/services/migration_orchestrator.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,21 @@ def __init__(
5858
cidx_config_path: Path to CIDX server config.
5959
skip_key_testing: If True, skip SSH authentication testing.
6060
"""
61+
# Get server directory from config service for consistent paths
62+
from .config_service import get_config_service
63+
64+
config_service = get_config_service()
65+
server_dir = config_service.config_manager.server_dir
66+
db_path = server_dir / "data" / "cidx_server.db"
67+
6168
if ssh_dir is None:
6269
ssh_dir = Path.home() / ".ssh"
6370
if metadata_dir is None:
64-
metadata_dir = Path.home() / ".code-indexer-server" / "ssh_keys"
71+
metadata_dir = server_dir / "data" / "ssh_keys"
6572
if migration_metadata_path is None:
66-
migration_metadata_path = (
67-
Path.home() / ".code-indexer-server" / "ssh_migration.json"
68-
)
73+
migration_metadata_path = server_dir / "ssh_migration.json"
6974
if cidx_config_path is None:
70-
cidx_config_path = Path.home() / ".code-indexer-server" / "config.json"
75+
cidx_config_path = server_dir / "config.json"
7176

7277
self.ssh_dir = ssh_dir
7378
self.metadata_dir = metadata_dir
@@ -84,6 +89,8 @@ def __init__(
8489
self.key_manager = SSHKeyManager(
8590
ssh_dir=ssh_dir,
8691
metadata_dir=metadata_dir,
92+
use_sqlite=True,
93+
db_path=db_path,
8794
)
8895

8996
def should_run_migration(self) -> bool:

src/code_indexer/server/web/routes.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def _get_token_manager() -> CITokenManager:
3636

3737
config_service = get_config_service()
3838
server_dir = config_service.config_manager.server_dir
39-
db_path = server_dir / "cidx.db"
39+
db_path = server_dir / "data" / "cidx_server.db"
4040

4141
return CITokenManager(
4242
server_dir_path=str(server_dir),
@@ -45,6 +45,23 @@ def _get_token_manager() -> CITokenManager:
4545
)
4646

4747

48+
def _get_ssh_key_manager():
49+
"""Create SSHKeyManager with SQLite backend (Story #702 migration)."""
50+
from ..services.config_service import get_config_service
51+
from ..services.ssh_key_manager import SSHKeyManager
52+
53+
config_service = get_config_service()
54+
server_dir = config_service.config_manager.server_dir
55+
db_path = server_dir / "data" / "cidx_server.db"
56+
metadata_dir = server_dir / "data" / "ssh_keys"
57+
58+
return SSHKeyManager(
59+
metadata_dir=metadata_dir,
60+
use_sqlite=True,
61+
db_path=db_path,
62+
)
63+
64+
4865
# Get templates directory path
4966
TEMPLATES_DIR = Path(__file__).parent / "templates"
5067
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
@@ -4628,9 +4645,7 @@ async def ssh_keys_page(request: Request):
46284645
managed_keys = []
46294646
unmanaged_keys = []
46304647
try:
4631-
from ..services.ssh_key_manager import SSHKeyManager
4632-
4633-
manager = SSHKeyManager()
4648+
manager = _get_ssh_key_manager()
46344649
key_list = manager.list_keys()
46354650
managed_keys = key_list.managed
46364651
unmanaged_keys = key_list.unmanaged
@@ -4675,9 +4690,7 @@ def _create_ssh_keys_page_response(
46754690
managed_keys = []
46764691
unmanaged_keys = []
46774692
try:
4678-
from ..services.ssh_key_manager import SSHKeyManager
4679-
4680-
manager = SSHKeyManager()
4693+
manager = _get_ssh_key_manager()
46814694
key_list = manager.list_keys()
46824695
managed_keys = key_list.managed
46834696
unmanaged_keys = key_list.unmanaged
@@ -4730,13 +4743,12 @@ async def create_ssh_key(
47304743
)
47314744

47324745
try:
4733-
from ..services.ssh_key_manager import SSHKeyManager
47344746
from ..services.ssh_key_generator import (
47354747
InvalidKeyNameError,
47364748
KeyAlreadyExistsError,
47374749
)
47384750

4739-
manager = SSHKeyManager()
4751+
manager = _get_ssh_key_manager()
47404752
manager.create_key(
47414753
name=key_name,
47424754
key_type=key_type,
@@ -4785,9 +4797,7 @@ async def delete_ssh_key(
47854797
)
47864798

47874799
try:
4788-
from ..services.ssh_key_manager import SSHKeyManager
4789-
4790-
manager = SSHKeyManager()
4800+
manager = _get_ssh_key_manager()
47914801
manager.delete_key(key_name)
47924802

47934803
return _create_ssh_keys_page_response(
@@ -4824,9 +4834,9 @@ async def assign_host_to_key(
48244834
)
48254835

48264836
try:
4827-
from ..services.ssh_key_manager import SSHKeyManager, HostConflictError
4837+
from ..services.ssh_key_manager import HostConflictError
48284838

4829-
manager = SSHKeyManager()
4839+
manager = _get_ssh_key_manager()
48304840
manager.assign_key_to_host(key_name, hostname)
48314841

48324842
return _create_ssh_keys_page_response(

0 commit comments

Comments
 (0)