Getting Started with Bookmarks
In this tutorial, you will learn how to use the core bookmarking functionality of the API. By the end of this guide, you will be able to initialize the central service, create a validated bookmark, retrieve it from the cache, and manage its lifecycle.
Prerequisites
Before starting, ensure you have the project dependencies installed and the application structure in place. This tutorial assumes you are working within the app package context.
Step 1: Initializing the Bookmark Service
The BookmarkService is the primary entry point for all bookmark operations. It is implemented as a Singleton, meaning that every time you instantiate it, you receive the same instance. This ensures that the internal cache and search index remain consistent across your application.
from app.services.bookmark_service import BookmarkService
# Obtain the service instance
service = BookmarkService()
When you call BookmarkService(), the class internally executes _init_services(). This bootstraps the BookmarkRepository for database access, an LRUCache for performance, and a SearchIndex for full-text search.
Step 2: Creating Your First Bookmark
To create a bookmark, you pass a dictionary of data to the create_bookmark method. This method follows a specific return pattern: it returns a tuple containing the created Bookmark object (or None) and an error message (or None).
# Define your bookmark data
data = {
"url": "https://github.com/vik-advani",
"title": "Project Repository",
"description": "The source code for this API."
}
# Attempt to create the bookmark
bookmark, error = service.create_bookmark(data)
if error:
print(f"Failed to create bookmark: {error}")
else:
print(f"Successfully created bookmark with ID: {bookmark.id}")
The create_bookmark method performs several actions:
- Validation: It checks that the
urlis a valid format (starting withhttp,https, orlocalhost) and that thetitleis present and under 256 characters. - Persistence: It saves the bookmark to the database via the repository.
- Indexing: It adds the bookmark to the search index.
- Cache Management: It invalidates any existing cache entry for this ID to ensure data consistency.
Step 3: Retrieving and Listing Bookmarks
Once a bookmark is created, you can retrieve it by its unique ID. The service automatically checks the internal LRUCache before querying the database.
# Retrieve a single bookmark by ID
bookmark_id = bookmark.id # From the previous step
retrieved = service.get_bookmark(bookmark_id)
if retrieved:
print(f"Found: {retrieved.title} ({retrieved.url})")
# List bookmarks with pagination
bookmarks, total_count = service.list_bookmarks(page=1, per_page=10)
print(f"Showing {len(bookmarks)} of {total_count} total bookmarks.")
The get_bookmark method populates the cache on a "miss." If the bookmark is found in the database, it is stored in the LRUCache (which has a default max_size of 256) for faster subsequent lookups.
Step 4: Updating and Soft-Deleting
The service provides methods to modify the state of a bookmark. Note that delete_bookmark does not permanently remove the record; instead, it performs a "soft-delete" by moving the bookmark to the trash.
# Update the title
update_data = {"title": "Updated Project Repository"}
updated_bookmark, error = service.update_bookmark(bookmark_id, update_data)
if not error:
print("Bookmark updated successfully.")
# Soft-delete (trash) the bookmark
success = service.delete_bookmark(bookmark_id)
if success:
print("Bookmark moved to trash.")
When you call delete_bookmark, the service:
- Retrieves the bookmark.
- Calls the
trash()method on theBookmarkmodel. - Saves the updated status to the repository.
- Invalidates the cache for that ID.
Summary and Next Steps
You have successfully used the BookmarkService to manage the lifecycle of a bookmark. You learned how to:
- Access the singleton service.
- Handle the
(result, error)return pattern. - Leverage the built-in validation and caching.
- Perform soft-deletes.
To further explore the API, you can look into Tag Operations using service.create_tag() or Collection Operations using service.add_to_collection(), both of which are managed through this same service.