feat(storage): ensure thumbnails use FileStore interface #132

Open
opened 2026-02-17 16:12:30 +00:00 by forbes · 0 comments
Owner

Summary

Verify and update thumbnail storage to use the FileStore interface consistently, ensuring thumbnails work with the filesystem backend.

Context

Thumbnails are stored in two distinct patterns in the codebase, and there is a discrepancy between the key generator functions and actual handler usage:

Pattern 1: Item-level thumbnails (used by HandleSetItemThumbnail)

  • Handler: HandleSetItemThumbnail in internal/api/file_handlers.go
  • Key: items/{itemID}/thumbnail.png
  • DB column: items.thumbnail_key (added by migration 011_item_files.sql)
  • Current flow: Accepts {object_key} from a presigned temp upload, copies to permanent key via s.storage.Copy()

Pattern 2: Revision-level thumbnails (key generator exists but usage unclear)

  • Function: storage.ThumbnailKey(partNumber, revision) in internal/storage/storage.go
  • Key: thumbnails/{partNumber}/rev{N}.png
  • DB column: revisions.thumbnail_key (*string field in Revision struct)
  • Usage: The ThumbnailKey() function exists as a standalone helper but its actual usage in handlers needs verification

Discrepancy

The HandleSetItemThumbnail handler uses items/{itemID}/thumbnail.png (item-scoped), while storage.ThumbnailKey() generates thumbnails/{partNumber}/rev{N}.png (revision-scoped). These are different key patterns serving different purposes.

Requirements

1. Audit thumbnail usage

  • Trace all code paths that read/write thumbnails
  • Determine if storage.ThumbnailKey() is actually called anywhere besides the function definition
  • Map which thumbnail paths exist in production MinIO buckets

2. Ensure filesystem compatibility

  • Item thumbnails (HandleSetItemThumbnail): Already uses s.storage.Copy() — works with FileStore interface after feat(storage): define FileStore interface abstraction (#126)
  • The presigned upload flow for thumbnails needs the same direct-upload adaptation as item files (covered in #129)
  • Verify ThumbnailKey() paths work correctly as filesystem paths (no special characters, reasonable depth)

3. Verify no MinIO-specific URLs leak

  • Check that thumbnail URLs served to the frontend are relative API paths, not MinIO presigned URLs
  • If thumbnails are served via a dedicated endpoint, ensure it uses FileStore.Get() not MinIO-specific methods
  • Check the item API response — thumbnail_key field (lines ~535 and ~1479 of handlers.go) — ensure it is a storage key, not a URL

4. Clean up if needed

  • If ThumbnailKey() is unused, remove it to avoid confusion
  • If both patterns are used, document the distinction
  • Ensure items.thumbnail_key and revisions.thumbnail_key DB columns are handled correctly during storage migration (#130)

Files to check

  • internal/storage/storage.goThumbnailKey() function
  • internal/api/file_handlers.goHandleSetItemThumbnail
  • internal/api/handlers.go — thumbnail_key in API responses
  • internal/db/items.goSetThumbnailKey(), Item.ThumbnailKey field
  • internal/db/revisions.go or items.go — Revision.ThumbnailKey field
  • Frontend code consuming thumbnail_key

Acceptance criteria

  • All thumbnail read/write paths use FileStore interface
  • Thumbnails work with filesystem backend
  • No MinIO-specific URLs in API responses or frontend
  • Dead code removed if ThumbnailKey() is unused
  • Thumbnail migration handled by data migration script (#130)

Priority

P2

Depends on

  • #126 (FileStore interface)
  • #127 (filesystem backend)

Part of

Storage Migration: MinIO → PostgreSQL + Filesystem

## Summary Verify and update thumbnail storage to use the `FileStore` interface consistently, ensuring thumbnails work with the filesystem backend. ## Context Thumbnails are stored in two distinct patterns in the codebase, and there is a discrepancy between the key generator functions and actual handler usage: ### Pattern 1: Item-level thumbnails (used by `HandleSetItemThumbnail`) - **Handler**: `HandleSetItemThumbnail` in `internal/api/file_handlers.go` - **Key**: `items/{itemID}/thumbnail.png` - **DB column**: `items.thumbnail_key` (added by migration `011_item_files.sql`) - **Current flow**: Accepts `{object_key}` from a presigned temp upload, copies to permanent key via `s.storage.Copy()` ### Pattern 2: Revision-level thumbnails (key generator exists but usage unclear) - **Function**: `storage.ThumbnailKey(partNumber, revision)` in `internal/storage/storage.go` - **Key**: `thumbnails/{partNumber}/rev{N}.png` - **DB column**: `revisions.thumbnail_key` (`*string` field in `Revision` struct) - **Usage**: The `ThumbnailKey()` function exists as a standalone helper but its actual usage in handlers needs verification ### Discrepancy The `HandleSetItemThumbnail` handler uses `items/{itemID}/thumbnail.png` (item-scoped), while `storage.ThumbnailKey()` generates `thumbnails/{partNumber}/rev{N}.png` (revision-scoped). These are different key patterns serving different purposes. ## Requirements ### 1. Audit thumbnail usage - Trace all code paths that read/write thumbnails - Determine if `storage.ThumbnailKey()` is actually called anywhere besides the function definition - Map which thumbnail paths exist in production MinIO buckets ### 2. Ensure filesystem compatibility - Item thumbnails (`HandleSetItemThumbnail`): Already uses `s.storage.Copy()` — works with `FileStore` interface after #126 - The presigned upload flow for thumbnails needs the same direct-upload adaptation as item files (covered in #129) - Verify `ThumbnailKey()` paths work correctly as filesystem paths (no special characters, reasonable depth) ### 3. Verify no MinIO-specific URLs leak - Check that thumbnail URLs served to the frontend are relative API paths, not MinIO presigned URLs - If thumbnails are served via a dedicated endpoint, ensure it uses `FileStore.Get()` not MinIO-specific methods - Check the item API response — `thumbnail_key` field (lines ~535 and ~1479 of `handlers.go`) — ensure it is a storage key, not a URL ### 4. Clean up if needed - If `ThumbnailKey()` is unused, remove it to avoid confusion - If both patterns are used, document the distinction - Ensure `items.thumbnail_key` and `revisions.thumbnail_key` DB columns are handled correctly during storage migration (#130) ## Files to check - `internal/storage/storage.go` — `ThumbnailKey()` function - `internal/api/file_handlers.go` — `HandleSetItemThumbnail` - `internal/api/handlers.go` — thumbnail_key in API responses - `internal/db/items.go` — `SetThumbnailKey()`, `Item.ThumbnailKey` field - `internal/db/revisions.go` or items.go — `Revision.ThumbnailKey` field - Frontend code consuming thumbnail_key ## Acceptance criteria - [ ] All thumbnail read/write paths use `FileStore` interface - [ ] Thumbnails work with filesystem backend - [ ] No MinIO-specific URLs in API responses or frontend - [ ] Dead code removed if `ThumbnailKey()` is unused - [ ] Thumbnail migration handled by data migration script (#130) ## Priority P2 ## Depends on - #126 (FileStore interface) - #127 (filesystem backend) ## Part of Storage Migration: MinIO → PostgreSQL + Filesystem
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/silo#132