Skip to content

Commit 48d2977

Browse files
committed
Add task types and improve daemon tests
- Create types.py with BaseTask, TaskType enum, and typed task definitions using Literal types - Update daemon.py to use new types, remove _write_debug_log calls, and add embedding method stubs - Replace logger assertions in tests with ASTChunker.chunk_file spies for better integration testing
1 parent 92471f6 commit 48d2977

File tree

3 files changed

+213
-134
lines changed

3 files changed

+213
-134
lines changed

src/mcp_code_indexer/vector_mode/daemon.py

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,23 @@
77

88
import asyncio
99
import logging
10-
import signal
1110
import sys
1211
from pathlib import Path
13-
from typing import Dict, List, Optional, Set
14-
import json
12+
from typing import Any, Dict, List, Optional, Set
1513
import time
1614

1715
from ..database.database import DatabaseManager
1816
from ..database.models import Project
1917
from .config import VectorConfig, load_vector_config
2018
from .monitoring.file_watcher import create_file_watcher, FileWatcher
21-
from .monitoring.utils import _write_debug_log
19+
2220
from .monitoring.change_detector import FileChange, ChangeType
2321
from .chunking.ast_chunker import ASTChunker
22+
from .types import (
23+
ScanProjectTask,
24+
VectorDaemonTaskType,
25+
ProcessFileChangeTask,
26+
)
2427

2528
logger = logging.getLogger(__name__)
2629

@@ -75,8 +78,8 @@ def callback(change: FileChange) -> None:
7578
"""Non-blocking callback that queues file change processing."""
7679
try:
7780
# Create file change processing task
78-
task_item = {
79-
"type": "process_file_change",
81+
task_item: ProcessFileChangeTask = {
82+
"type": VectorDaemonTaskType.PROCESS_FILE_CHANGE,
8083
"project_name": project_name,
8184
"change": change,
8285
"timestamp": time.time(),
@@ -223,8 +226,8 @@ async def _monitor_projects(self) -> None:
223226

224227
async def _queue_project_scan(self, project_name: str, folder_path: str) -> None:
225228
"""Queue a project for scanning and indexing."""
226-
task = {
227-
"type": "scan_project",
229+
task: ScanProjectTask = {
230+
"type": VectorDaemonTaskType.SCAN_PROJECT,
228231
"project_name": project_name,
229232
"folder_path": folder_path,
230233
"timestamp": time.time(),
@@ -268,20 +271,19 @@ async def _process_task(self, task: dict, worker_id: str) -> None:
268271
"""Process a queued task."""
269272
task_type = task.get("type")
270273

271-
if task_type == "scan_project":
274+
if task_type == VectorDaemonTaskType.SCAN_PROJECT:
272275
await self._process_project_scan(task, worker_id)
273-
elif task_type == "process_file_change":
276+
elif task_type == VectorDaemonTaskType.PROCESS_FILE_CHANGE:
274277
await self._process_file_change_task(task, worker_id)
275278
else:
276279
logger.warning(f"Unknown task type: {task_type}")
277280

278-
async def _process_file_change_task(self, task: dict, worker_id: str) -> None:
281+
async def _process_file_change_task(
282+
self, task: ProcessFileChangeTask, worker_id: str
283+
) -> None:
279284
"""Process a file change task."""
280285
project_name: str = task["project_name"]
281286
change: FileChange = task["change"]
282-
_write_debug_log(
283-
f"Worker {worker_id}: Processing file change for {change.path}"
284-
)
285287
logger.info(
286288
f"Worker {worker_id}: File change detected for project {project_name}: {change.path} ({change.change_type.value})",
287289
extra={
@@ -347,22 +349,26 @@ async def _process_file_change_task(self, task: dict, worker_id: str) -> None:
347349
},
348350
)
349351

350-
# Write detailed debug information
351-
_write_debug_log(
352-
f"Worker {worker_id}: File {change.path} chunking details:\n"
353-
f" Total chunks: {chunk_count}\n"
354-
f" Chunk types: {chunk_types}\n"
355-
f" Redacted chunks: {redacted_count}\n"
356-
f" Sample chunks:\n"
357-
+ "\n".join(
358-
[
359-
f" [{i}] {chunk.chunk_type.value} - {chunk.name or 'unnamed'} "
360-
f"(lines {chunk.start_line}-{chunk.end_line}, "
361-
f"{len(chunk.content)} chars, redacted: {chunk.redacted})"
362-
for i, chunk in enumerate(chunks[:3]) # Show first 3 chunks
363-
]
364-
)
352+
# Log detailed debug information
353+
sample_chunks = [
354+
f" [{i}] {chunk.chunk_type.value} - {chunk.name or 'unnamed'} "
355+
f"(lines {chunk.start_line}-{chunk.end_line}, "
356+
f"{len(chunk.content)} chars, redacted: {chunk.redacted})"
357+
for i, chunk in enumerate(chunks[:3]) # Show first 3 chunks
358+
]
359+
logger.debug(
360+
f"Worker {worker_id}: File {change.path} chunking details: "
361+
f"Total chunks: {chunk_count}, "
362+
f"Chunk types: {chunk_types}, "
363+
f"Redacted chunks: {redacted_count}, "
364+
f"Sample chunks: {', '.join(sample_chunks)}"
365+
)
366+
367+
# Generate and store embeddings for chunks
368+
embeddings = await self._generate_embeddings(
369+
chunks, project_name, change.path
365370
)
371+
await self._store_embeddings(embeddings, project_name, change.path)
366372

367373
# Only increment stats for successfully chunked files
368374
self.stats["files_processed"] += 1
@@ -421,29 +427,25 @@ async def _process_project_scan(self, task: dict, worker_id: str) -> None:
421427
ignore_patterns=self.config.ignore_patterns,
422428
debounce_interval=self.config.watch_debounce_ms / 1000.0,
423429
)
424-
_write_debug_log(
425-
f"VectorDaemon: Created watcher for {project_name}"
426-
)
430+
logger.debug(f"VectorDaemon: Created watcher for {project_name}")
427431
# Initialize the watcher
428432
await watcher.initialize()
429-
_write_debug_log(
433+
logger.debug(
430434
f"VectorDaemon: Initialized watcher for {project_name}"
431435
)
432436
# Add change callback
433437
watcher.add_change_callback(self._on_file_change(project_name))
434-
_write_debug_log(
438+
logger.debug(
435439
f"VectorDaemon: Added change callback for {project_name}"
436440
)
437441

438442
# Start watching
439443
watcher.start_watching()
440-
_write_debug_log(
441-
f"VectorDaemon: Started watching for {project_name}"
442-
)
444+
logger.debug(f"VectorDaemon: Started watching for {project_name}")
443445

444446
# Store watcher for later cleanup
445447
self.file_watchers[project_name] = watcher
446-
_write_debug_log(f"VectorDaemon: Stored watcher for {project_name}")
448+
logger.debug(f"VectorDaemon: Stored watcher for {project_name}")
447449

448450
logger.info(
449451
f"File watcher started for project {project_name}",
@@ -554,6 +556,20 @@ def get_status(self) -> dict:
554556
"file_watcher_stats": watcher_stats,
555557
}
556558

559+
async def _generate_embeddings(
560+
self, chunks: list, project_name: str, file_path
561+
) -> list[list[float]]:
562+
"""Generate embeddings for file chunks."""
563+
# TODO: implement
564+
return []
565+
566+
async def _store_embeddings(
567+
self, embeddings: list[list[float]], project_name: str, file_path
568+
) -> None:
569+
"""Store embeddings in vector database."""
570+
# TODO: implement
571+
pass
572+
557573

558574
async def start_vector_daemon(
559575
config_path: Optional[Path] = None,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Type definitions for vector mode daemon tasks."""
2+
3+
from enum import Enum
4+
from typing import TypedDict, Literal
5+
6+
from mcp_code_indexer.vector_mode.monitoring.change_detector import FileChange
7+
8+
9+
class VectorDaemonTaskType(Enum):
10+
"""Task types for daemon processing queue."""
11+
12+
SCAN_PROJECT = "scan_project"
13+
PROCESS_FILE_CHANGE = "process_file_change"
14+
15+
16+
class BaseTask(TypedDict):
17+
"""Base task with common fields."""
18+
19+
project_name: str
20+
timestamp: float
21+
22+
23+
class ScanProjectTask(BaseTask):
24+
"""Task for scanning and indexing a project."""
25+
26+
type: Literal[VectorDaemonTaskType.SCAN_PROJECT]
27+
folder_path: str
28+
29+
30+
class ProcessFileChangeTask(BaseTask):
31+
"""Task for processing file changes."""
32+
33+
type: Literal[VectorDaemonTaskType.PROCESS_FILE_CHANGE]
34+
change: "FileChange" # Forward reference to avoid circular import
35+
36+
37+
# Union type for all task types
38+
TaskItem = ScanProjectTask | ProcessFileChangeTask

0 commit comments

Comments
 (0)