Managing Content via BookmarkService
The BookmarkService acts as the central facade for managing bookmarks, tags, and collections. It orchestrates business logic, including validation, persistence via the repository, search indexing, and cache management.
Accessing the Service Instance
The BookmarkService is implemented as a singleton to ensure consistent state (like the search index and cache) across the application. You should instantiate it at the module level in your route handlers.
from app.services.bookmark_service import BookmarkService
# Obtain the singleton instance
_service = BookmarkService()
Managing Bookmarks
The service provides methods for the full lifecycle of a bookmark. Methods that perform validation return a tuple of (result, error_message).
Creating and Updating Bookmarks
When creating or updating, the service automatically validates the URL and title, updates the search index, and invalidates the cache.
# Creating a bookmark
data = {
"url": "https://example.com",
"title": "Example Domain",
"description": "A useful example site"
}
bookmark, error = _service.create_bookmark(data)
if error:
print(f"Validation failed: {error}")
else:
print(f"Created bookmark: {bookmark.id}")
# Updating a bookmark
update_data = {"title": "New Title"}
updated_bookmark, error = _service.update_bookmark(bookmark.id, update_data)
Searching Bookmarks
The service provides a full_text_search method that queries the internal SearchIndex across bookmark titles and descriptions.
results = _service.full_text_search("example", limit=10)
for b in results:
print(b.title)
Managing Tags
Tags are managed through the service to ensure that deletions are handled safely across the entire system.
Creating Tags
Tag names are validated against a set of reserved keywords.
tag_data = {"name": "Research", "color": "blue"}
tag, error = _service.create_tag(tag_data)
if error:
# Error might be "Tag name is required" or "'all' is a reserved tag name"
print(f"Error: {error}")
Deleting Tags and Cleanup
When you delete a tag via delete_tag, the service automatically removes that tag from all bookmarks that currently use it and invalidates their cache entries.
# This removes the tag from the system and all associated bookmarks
success = _service.delete_tag("tag-id-123")
Organizing with Collections
Collections allow you to group bookmarks. The service handles the logic for adding and removing bookmarks from these groups.
# Create a collection
collection, error = _service.create_collection({"name": "Project Alpha"})
if collection:
# Add a bookmark to the collection
success = _service.add_to_collection(collection.id, "bookmark-id-456")
if not success:
print("Collection not found or bookmark already in collection")
# Remove a bookmark
_service.remove_from_collection(collection.id, "bookmark-id-456")
Troubleshooting and Constraints
- Reserved Tag Names: You cannot create tags named
all,untagged,archived, ortrash. These are reserved for system filters. - Validation Limits:
- Titles are limited to 256 characters.
- Descriptions are limited to 2048 characters.
- Tag names are limited to 50 characters.
- Singleton State in Tests: Because
BookmarkServiceis a singleton, state persists between tests. Use the internal_reset()method in your test setup/teardown to clear the repository, cache, and search index.def setup_method(self):
BookmarkService()._reset() - Soft Deletion: The
delete_bookmarkmethod performs a "soft delete" by moving the bookmark to the trash. Userestore_bookmarkto bring it back orarchive_bookmarkto move it to the archive.