Skip to main content

Managing Bookmark Lifecycle

In etchblok-test-api, you manage the lifecycle of bookmarks using the BookmarkService. This service acts as a singleton facade that coordinates validation, persistence via the repository, full-text indexing, and transparent caching.

Creating a Bookmark

To create a new bookmark, use the create_bookmark method. This method performs URL and title validation before persisting the entity. It returns a tuple containing the created Bookmark object and an error message (if any).

from app.services.bookmark_service import BookmarkService

service = BookmarkService()

data = {
"url": "https://example.com",
"title": "Example Domain",
"description": "A useful site for testing."
}

bookmark, error = service.create_bookmark(data)

if error:
# Handle validation error (e.g., invalid URL format)
print(f"Failed to create bookmark: {error}")
else:
print(f"Created bookmark with ID: {bookmark.id}")

Updating Bookmark Details

The update_bookmark method supports partial updates. You only need to provide the fields you wish to change. The service automatically updates the updated_at timestamp via the _touch() method and invalidates the cache.

update_data = {
"title": "Updated Example Title",
"description": "An updated description."
}

# Partially update the bookmark
bookmark, error = service.update_bookmark("bookmark_id_123", update_data)

if error:
print(f"Update failed: {error}")
elif not bookmark:
print("Bookmark not found")

Managing Bookmark Status (Archive, Trash, Restore)

etchblok-test-api uses a status-based lifecycle defined in BookmarkStatus (ACTIVE, ARCHIVED, TRASHED). Instead of permanent deletion, the service implements soft-deletion by moving bookmarks to the "trash".

Archiving a Bookmark

Archiving moves a bookmark out of the primary view without deleting it.

bookmark = service.archive_bookmark("bookmark_id_123")
if bookmark:
assert bookmark.status.value == "archived"

Soft-Deleting (Trashing)

The delete_bookmark method performs a soft-delete by transitioning the status to TRASHED.

# Soft-deletes the bookmark
success = service.delete_bookmark("bookmark_id_123")
if not success:
print("Bookmark not found or already deleted")

Restoring a Bookmark

You can restore a trashed or archived bookmark back to the ACTIVE status.

bookmark = service.restore_bookmark("bookmark_id_123")
if bookmark:
assert bookmark.status.value == "active"

Retrieving and Listing Bookmarks

The service provides methods for single retrieval and paginated listing. Single lookups are optimized using an internal LRUCache.

Fetching by ID

# Uses LRUCache internally to speed up repeated lookups
bookmark = service.get_bookmark("bookmark_id_123")

Listing with Filters

You can list bookmarks with pagination and optional status filtering (e.g., to show only archived items).

# List the first 10 archived bookmarks
bookmarks, total_count = service.list_bookmarks(
page=1,
per_page=10,
status="archived"
)

Troubleshooting

Validation Failures

The create_bookmark and update_bookmark methods return an error string if validation fails. Common reasons include:

  • Invalid URL: URLs must start with http:// or https://.
  • Missing Title: The title field is required and cannot be empty.

Soft-Delete Behavior

If you call delete_bookmark, the record is not removed from the database. It remains in the system with a TRASHED status. To permanently remove data, you would need to interact with the BookmarkRepository directly, as the BookmarkService does not expose a hard-delete method.

Cache Invalidation

The BookmarkService automatically invalidates the cache on every update, deletion, or status change. If you modify bookmarks directly through the repository, the cache may become stale. Always use the BookmarkService for lifecycle operations to ensure consistency across the cache and search index.