change document api to uset get by id

This commit is contained in:
phernandez
2024-12-21 23:46:05 -06:00
parent 0f88c6bc6b
commit 3541c2873d
3 changed files with 57 additions and 33 deletions
+5 -5
View File
@@ -49,21 +49,21 @@ async def list_documents(
return [DocumentCreateResponse.model_validate(doc.__dict__) for doc in documents]
@router.get("/{path:path}", response_model=DocumentResponse)
@router.get("/{id:int}", response_model=DocumentResponse)
async def get_document(
path: str,
id: int,
service: DocumentServiceDep,
) -> DocumentResponse:
"""Get a document by path."""
"""Get a document by ID."""
try:
document, content = await service.read_document(path)
document, content = await service.read_document_by_id(id)
doc_dict = document.__dict__ | {"content": content}
response = DocumentResponse.model_validate(doc_dict)
return response
except DocumentNotFoundError:
raise HTTPException(
status_code=404,
detail=f"Document not found: {path}"
detail=f"Document not found: {id}"
)
except DocumentWriteError as e:
raise HTTPException(status_code=400, detail=str(e))
+44 -23
View File
@@ -3,7 +3,7 @@
import hashlib
from datetime import datetime, UTC
from pathlib import Path
from typing import Optional, Dict, Any, List
from typing import Optional, Dict, Any, List, Tuple
import yaml
from loguru import logger
@@ -60,18 +60,16 @@ class DocumentService(BaseService[DocumentRepository]):
except Exception as e:
raise DocumentWriteError(f"Failed to create directory: {parent}: {e}")
async def add_frontmatter(self, content: str, doc_id: int, metadata: Optional[Dict[str, Any]] = None) -> str:
async def add_frontmatter(
self, content: str, doc_id: int, metadata: Optional[Dict[str, Any]] = None
) -> str:
"""Add frontmatter to document content."""
# Generate frontmatter with timestamps
now = datetime.now(UTC).isoformat()
frontmatter = {
"id": doc_id,
"created": now,
"modified": now
}
frontmatter = {"id": doc_id, "created": now, "modified": now}
if metadata:
frontmatter.update(metadata)
yaml_fm = yaml.dump(frontmatter, sort_keys=False)
return f"---\n{yaml_fm}---\n\n{content}"
@@ -104,10 +102,7 @@ class DocumentService(BaseService[DocumentRepository]):
try:
# 1. Create initial DB record to get ID
doc = await self.repository.create({
"path": str(path),
"doc_metadata": metadata
})
doc = await self.repository.create({"path": str(path), "doc_metadata": metadata})
# 2. Add frontmatter with DB-generated ID
content_with_frontmatter = await self.add_frontmatter(content, doc.id, metadata)
@@ -122,11 +117,41 @@ class DocumentService(BaseService[DocumentRepository]):
except Exception as e:
# Clean up on any failure
if 'doc' in locals(): # DB record was created
if "doc" in locals(): # DB record was created
await self.repository.delete(doc.id)
file_path.unlink(missing_ok=True)
raise DocumentWriteError(f"Failed to create document: {e}")
async def read_document_by_id(self, id: int) -> Tuple[Document, str]:
"""
Read a document and its content by ID.
Args:
id: Document ID
Returns:
Tuple of (document record, content)
Raises:
DocumentNotFoundError: If document doesn't exist
DocumentError: If file read fails
"""
logger.debug(f"Reading document with ID {id}")
# Get document record
query = select(Document).where(Document.id == id)
doc = await self.repository.find_one(query)
if not doc:
raise DocumentNotFoundError(f"Document not found: {id}")
# Read content since file is source of truth
try:
file_path = Path(doc.path)
content = file_path.read_text()
return doc, content
except Exception as e:
raise DocumentError(f"Failed to read document {id}: {e}")
async def read_document(self, path: str) -> tuple[Document, str]:
"""
Read a document and its content.
@@ -167,15 +192,15 @@ class DocumentService(BaseService[DocumentRepository]):
) -> Document:
"""
Update a document using its ID.
Args:
id: Document ID
content: New content
metadata: Optional new metadata
Returns:
Updated document record
Raises:
DocumentNotFoundError: If document doesn't exist
DocumentWriteError: If update fails
@@ -189,11 +214,7 @@ class DocumentService(BaseService[DocumentRepository]):
raise DocumentNotFoundError(f"Document not found: {id}")
# Use existing path to update file
return await self.update_document(
path=document.path,
content=content,
metadata=metadata
)
return await self.update_document(path=document.path, content=content, metadata=metadata)
async def update_document(
self, path: str, content: str, metadata: Optional[Dict[str, Any]] = None
@@ -239,7 +260,7 @@ class DocumentService(BaseService[DocumentRepository]):
checksum = await self.compute_checksum(content)
update_data = {"checksum": checksum}
if metadata is not None:
update_data["doc_metadata"] = metadata
update_data["doc_metadata"] = metadata # pyright: ignore [reportArgumentType]
updated_document = await self.repository.update(doc.id, update_data)
assert updated_document is not None, f"Could not update document {doc.id}"
@@ -272,4 +293,4 @@ class DocumentService(BaseService[DocumentRepository]):
# Delete database record if it exists
doc = await self.repository.find_by_path(str(path))
if doc:
await self.repository.delete(doc.id)
await self.repository.delete(doc.id)