change entity.path_id to entity.permalink

This commit is contained in:
phernandez
2025-01-12 16:47:21 -06:00
parent 1f374e0133
commit c5d21276de
52 changed files with 714 additions and 687 deletions
+11 -11
View File
@@ -25,7 +25,7 @@ def entity_model_from_markdown(file_path: str, markdown: EntityMarkdown) -> Enti
model = EntityModel(
title=markdown.frontmatter.title,
entity_type=markdown.frontmatter.type,
path_id=markdown.frontmatter.id,
permalink=markdown.frontmatter.id,
file_path=file_path,
content_type="text/markdown",
summary=markdown.content.content,
@@ -65,21 +65,21 @@ class EntitySyncService:
model = entity_model_from_markdown(file_path, markdown)
# Mark as incomplete sync
model.checksum = None
model.checksum = None
return await self.entity_repository.add(model)
async def update_entity_and_observations(
self, path_id: str, markdown: EntityMarkdown
self, permalink: str, markdown: EntityMarkdown
) -> EntityModel:
"""First pass: Update entity fields and observations.
Updates everything except relations and sets null checksum
to indicate sync not complete.
"""
logger.debug(f"Updating entity and observations: {path_id}")
db_entity = await self.entity_repository.get_by_path_id(path_id)
logger.debug(f"Updating entity and observations: {permalink}")
db_entity = await self.entity_repository.get_by_permalink(permalink)
if not db_entity:
raise EntityNotFoundError(f"Entity not found: {path_id}")
raise EntityNotFoundError(f"Entity not found: {permalink}")
# Update fields from markdown
db_entity.title = markdown.frontmatter.title
@@ -88,7 +88,7 @@ class EntitySyncService:
# Clear observations for entity
await self.observation_repository.delete_by_fields(entity_id=db_entity.id)
# add new observations
observations = [
Observation(
@@ -122,14 +122,14 @@ class EntitySyncService:
checksum: Final checksum to set after relations are updated
"""
logger.debug(f"Updating relations for entity: {markdown.frontmatter.id}")
db_entity = await self.entity_repository.get_by_path_id(markdown.frontmatter.id)
db_entity = await self.entity_repository.get_by_permalink(markdown.frontmatter.id)
# get all entities from relations
target_entity_path_ids = [rel.target for rel in markdown.content.relations]
target_entities = await self.entity_repository.find_by_path_ids(target_entity_path_ids)
target_entity_permalinks = [rel.target for rel in markdown.content.relations]
target_entities = await self.entity_repository.find_by_permalinks(target_entity_permalinks)
# dict by path
entity_by_path = {e.path_id: e for e in target_entities}
entity_by_path = {e.permalink: e for e in target_entities}
# Clear and update relations
await self.relation_repository.delete_outgoing_relations_from_entity(db_entity.id)
+24 -18
View File
@@ -1,7 +1,8 @@
"""Service for detecting changes between filesystem and database."""
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, Sequence, Any
from typing import Dict, Sequence
from loguru import logger
@@ -10,22 +11,24 @@ from basic_memory.repository.entity_repository import EntityRepository
from basic_memory.sync.utils import SyncReport
from basic_memory.utils.file_utils import compute_checksum
@dataclass
class FileState:
"""State of a file including file path, path_id and checksum info."""
"""State of a file including file path, permalink and checksum info."""
file_path: str
path_id: str
permalink: str
checksum: str
@dataclass
@dataclass
class ScanResult:
"""Result of scanning a directory."""
# file_path -> checksum
files: Dict[str, str] = field(default_factory=dict)
# file_path -> error message
errors: Dict[str, str] = field(default_factory=dict)
errors: Dict[str, str] = field(default_factory=dict)
class FileChangeScanner:
@@ -34,9 +37,7 @@ class FileChangeScanner:
The filesystem is treated as the source of truth.
"""
def __init__(
self, entity_repository: EntityRepository
):
def __init__(self, entity_repository: EntityRepository):
self.entity_repository = entity_repository
async def scan_directory(self, directory: Path) -> ScanResult:
@@ -70,7 +71,7 @@ class FileChangeScanner:
checksum = await compute_checksum(content)
if checksum: # Only store valid checksums
result.files[rel_path] = checksum
result.files[rel_path] = checksum
else:
result.errors[rel_path] = "Failed to compute checksum"
@@ -85,13 +86,15 @@ class FileChangeScanner:
return result
async def find_changes(self, directory: Path, db_file_state: Dict[str, FileState]) -> SyncReport:
async def find_changes(
self, directory: Path, db_file_state: Dict[str, FileState]
) -> SyncReport:
"""
Find changes between filesystem and database.
Args:
directory: Directory to check
db_file_state: dict mapping file_path to DbState(path_id, checksum)
db_file_state: dict mapping file_path to DbState(permalink, checksum)
Returns:
SyncReport detailing changes
@@ -102,11 +105,11 @@ class FileChangeScanner:
# Build report
report = SyncReport()
# Find new and modified files
for file_path, checksum in current_files.items():
logger.debug(f"{file_path} ({checksum[:8]})")
if file_path not in db_file_state:
report.new.add(file_path)
elif checksum != db_file_state[file_path].checksum:
@@ -134,9 +137,7 @@ class FileChangeScanner:
return report
async def get_db_file_state(
self, db_records: Sequence[Entity]
) -> Dict[str, FileState]:
async def get_db_file_state(self, db_records: Sequence[Entity]) -> Dict[str, FileState]:
"""Get file_path and checksums from database.
Args:
db_records: database records
@@ -144,7 +145,12 @@ class FileChangeScanner:
Dict mapping file paths to FileState
:param db_records: the data from the db
"""
return {r.file_path: FileState(file_path=r.file_path, path_id=r.path_id, checksum=r.checksum) for r in db_records}
return {
r.file_path: FileState(
file_path=r.file_path, permalink=r.permalink, checksum=r.checksum
)
for r in db_records
}
async def find_knowledge_changes(self, directory: Path) -> SyncReport:
"""Find changes in knowledge directory."""
+3 -3
View File
@@ -56,10 +56,10 @@ class SyncService:
file_path, entity_markdown
)
else:
path_id = entity_markdown.frontmatter.id
logger.debug(f"Updating entity_markdown: {path_id}")
permalink = entity_markdown.frontmatter.id
logger.debug(f"Updating entity_markdown: {permalink}")
await self.knowledge_sync_service.update_entity_and_observations(
path_id, entity_markdown
permalink, entity_markdown
)
# Second pass: Process relations