diff --git a/src/basic_memory/cli/commands/sync.py b/src/basic_memory/cli/commands/sync.py index 652d60ba..82852c9b 100644 --- a/src/basic_memory/cli/commands/sync.py +++ b/src/basic_memory/cli/commands/sync.py @@ -58,8 +58,6 @@ async def get_sync_service(db_type=DatabaseType.FILESYSTEM): file_change_scanner = FileChangeScanner(entity_repository) # Initialize services - entity_service = EntityService(entity_repository) - knowledge_sync_service = EntitySyncService( entity_repository, observation_repository, relation_repository ) diff --git a/src/basic_memory/deps.py b/src/basic_memory/deps.py index b96842e8..bccd7513 100644 --- a/src/basic_memory/deps.py +++ b/src/basic_memory/deps.py @@ -150,10 +150,10 @@ RelationServiceDep = Annotated[RelationService, Depends(get_relation_service)] async def get_search_service( - search_repository: SearchRepositoryDep, entity_service: EntityServiceDep + search_repository: SearchRepositoryDep, entity_repository: EntityRepositoryDep ) -> SearchService: """Create SearchService with dependencies.""" - return SearchService(search_repository, entity_service) + return SearchService(search_repository, entity_repository) SearchServiceDep = Annotated[SearchService, Depends(get_search_service)] diff --git a/src/basic_memory/services/search_service.py b/src/basic_memory/services/search_service.py index d9afc696..d5a9dd98 100644 --- a/src/basic_memory/services/search_service.py +++ b/src/basic_memory/services/search_service.py @@ -1,13 +1,13 @@ """Service for search operations.""" -from typing import List, Optional, Any +from typing import List, Optional from fastapi import BackgroundTasks from loguru import logger from basic_memory.models import Entity +from basic_memory.repository import EntityRepository from basic_memory.repository.search_repository import SearchRepository -from basic_memory.services.entity_service import EntityService from basic_memory.schemas.search import SearchQuery, SearchResult, SearchItemType @@ -17,45 +17,38 @@ class SearchService: def __init__( self, search_repository: SearchRepository, - entity_service: EntityService, + entity_repository: EntityRepository, ): self.repository = search_repository - self.entity_service = entity_service + self.entity_repository = entity_repository async def init_search_index(self): """Create FTS5 virtual table if it doesn't exist.""" await self.repository.init_search_index() - - async def reindex_all( - self, - background_tasks: Optional[BackgroundTasks] = None - ) -> None: + + async def reindex_all(self, background_tasks: Optional[BackgroundTasks] = None) -> None: """Reindex all content from database.""" logger.info("Starting full reindex") - + # Clear and recreate search index await self.init_search_index() - + # Reindex all entities logger.debug("Indexing entities") - entities = await self.entity_service.get_all() + entities = await self.entity_repository.find_all() for entity in entities: await self.index_entity(entity, background_tasks) - + logger.info("Reindex complete") async def search( - self, - query: SearchQuery, - context: Optional[List[str]] = None + self, query: SearchQuery, context: Optional[List[str]] = None ) -> List[SearchResult]: """Search across all indexed content.""" return await self.repository.search(query, context) async def index_entity( - self, - entity: Entity, - background_tasks: Optional[BackgroundTasks] = None + self, entity: Entity, background_tasks: Optional[BackgroundTasks] = None ) -> None: """Index an entity and its components.""" # Build searchable content @@ -99,22 +92,13 @@ class SearchService: ) async def _do_index( - self, - content: str, - path_id: str, - file_path: str, - type: SearchItemType, - metadata: dict + self, content: str, path_id: str, file_path: str, type: SearchItemType, metadata: dict ) -> None: """Actually perform the indexing.""" await self.repository.index_item( - content=content, - path_id=path_id, - file_path=file_path, - type=type, - metadata=metadata + content=content, path_id=path_id, file_path=file_path, type=type, metadata=metadata ) - + async def delete_by_path_id(self, path_id: str): """Delete an item from the search index.""" - await self.repository.delete_by_path_id(path_id) \ No newline at end of file + await self.repository.delete_by_path_id(path_id) diff --git a/tests/conftest.py b/tests/conftest.py index 09f52b3e..59e1604f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -197,10 +197,10 @@ async def init_search_index(search_service): @pytest_asyncio.fixture async def search_service( search_repository: SearchRepository, - entity_service: EntityService, + entity_repository: EntityRepository, ) -> SearchService: """Create and initialize search service""" - service = SearchService(search_repository, entity_service) + service = SearchService(search_repository, entity_repository) await service.init_search_index() return service diff --git a/tests/sync/test_sync_knowledge.py b/tests/sync/test_sync_knowledge.py index 889fa0e7..bddef9f8 100644 --- a/tests/sync/test_sync_knowledge.py +++ b/tests/sync/test_sync_knowledge.py @@ -56,7 +56,7 @@ A test concept. await entity_service.repository.add(other) # Run sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify results entities = await entity_service.repository.find_all() @@ -100,7 +100,7 @@ modified: 2024-01-01 await create_test_file(knowledge_dir / "concept/depends_on_future.md", content) # Sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify entity created but no relations entity = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id( @@ -154,7 +154,7 @@ modified: 2024-01-01 await create_test_file(knowledge_dir / "concept/entity_b.md", content_b) # Sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify both entities and their relations entity_a = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id( @@ -229,7 +229,7 @@ modified: 2024-01-01 await create_test_file(knowledge_dir / "concept/duplicate_relations.md", content) # Sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify duplicates are handled entity = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id( @@ -271,7 +271,7 @@ modified: 2024-01-01 await create_test_file(knowledge_dir / "concept/invalid_category.md", content) # Sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify observations entity = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id( @@ -350,7 +350,7 @@ modified: 2024-01-01 await create_test_file(knowledge_dir / f"concept/entity_{name}.md", content) # Sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify all relations are created correctly regardless of order entity_a = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id( diff --git a/tests/sync/test_sync_service.py b/tests/sync/test_sync_service.py index 602349b8..405a382f 100644 --- a/tests/sync/test_sync_service.py +++ b/tests/sync/test_sync_service.py @@ -20,7 +20,7 @@ async def create_test_file(path: Path, content: str = "test content") -> None: @pytest.mark.asyncio async def test_sync_empty_directories(sync_service: SyncService, test_config: ProjectConfig): """Test syncing empty directories.""" - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Should not raise exceptions for empty dirs assert (test_config.knowledge_dir).exists() @@ -55,7 +55,7 @@ modified: 2024-01-01 doc_path.write_text("Modified during sync") # Run sync and modification concurrently - await asyncio.gather(sync_service.sync(test_config), modify_file()) + await asyncio.gather(sync_service.sync(test_config.knowledge_dir), modify_file()) # Verify final state doc = await sync_service.knowledge_sync_service.entity_repository.get_by_path_id("changing") @@ -96,7 +96,7 @@ modified: 2024-01-01 await create_test_file(test_config.knowledge_dir / "concept/incomplete.md", content) # Run sync - await sync_service.sync(test_config) + await sync_service.sync(test_config.knowledge_dir) # Verify entity was properly synced updated = await entity_service.get_by_path_id("concept/incomplete")