From 206b2a9d5bb3ed2ae28845212e31e3d773d87515 Mon Sep 17 00:00:00 2001 From: Francisco Penedo Alvarez Date: Wed, 1 Apr 2026 11:03:36 +0200 Subject: [PATCH] Fix #3: Old cover shown after updating book cover Caddy is set up to serve static files with aggressive caching, which is great for performance but can cause issues when updating book covers. To ensure users see the updated cover immediately, we need implement a cache-busting strategy. This involves generating a unique filename for each cover image based on its content, using a hash of the image data. By doing this, when a cover is updated, it will have a new filename, prompting browsers to fetch the new image instead of using the cached version. --- src/hxbooks/library.py | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/hxbooks/library.py b/src/hxbooks/library.py index 571d6d9..625e423 100644 --- a/src/hxbooks/library.py +++ b/src/hxbooks/library.py @@ -5,6 +5,7 @@ Clean service layer for book management, reading tracking, and wishlist operatio Separated from web interface concerns to enable both CLI and web access. """ +import hashlib import logging from collections import defaultdict from collections.abc import Sequence @@ -1013,32 +1014,27 @@ def download_book_cover(book: Book, image_url: str) -> bool: return False # Load image directly from file - with Image.open(source_path) as image: - processed_image = _process_cover_image(image) - - # Generate filename - extension = ".jpg" # Always save as JPEG - filename = f"book_{book.id}{extension}" - cover_path = covers_dir / filename - - # Save processed image - processed_image.save(cover_path, "JPEG", quality=85) + source = source_path else: # Handle HTTP(S) URLs response = requests.get(image_url, timeout=10, stream=True) response.raise_for_status() # Load image from response content - with Image.open(response.raw) as image: - processed_image = _process_cover_image(image) + source = response.raw - # Generate filename - extension = ".jpg" # Always save as JPEG - filename = f"book_{book.id}{extension}" - cover_path = covers_dir / filename + with Image.open(source) as image: + processed_image = _process_cover_image(image) - # Save processed image - processed_image.save(cover_path, "JPEG", quality=85) + # Generate filename + extension = ".jpg" # Always save as JPEG + # Hash the image to create a unique filename based on content + image_hash = hashlib.md5(processed_image.tobytes()).hexdigest() + filename = f"book_{book.id}_{image_hash}{extension}" + cover_path = covers_dir / filename + + # Save processed image + processed_image.save(cover_path, "JPEG", quality=85) # Update book record book.cover_image_path = filename