Skip to content

fix(thumbnails): use matched resolution for thumbnail cache keys#2727

Closed
MrCodeEU wants to merge 2 commits intoopencloud-eu:mainfrom
MrCodeEU:fix/thumbnails-honor-configured-resolutions
Closed

fix(thumbnails): use matched resolution for thumbnail cache keys#2727
MrCodeEU wants to merge 2 commits intoopencloud-eu:mainfrom
MrCodeEU:fix/thumbnails-honor-configured-resolutions

Conversation

@MrCodeEU
Copy link
Copy Markdown

@MrCodeEU MrCodeEU commented May 9, 2026

Summary

I noticed that in folders with many large images the previews loaded quite slow compared to Nextcloud or Immich.
Because of that i did some investigations and found that the images that the web interface loads are not actually the preview images. After some digging i found this bug and created a fix for it:

Fix thumbnail cache key generation so configured thumbnail resolutions are honored consistently.

When THUMBNAILS_RESOLUTIONS is configured, arbitrary client-requested preview sizes should be mapped to the closest
configured resolution. The thumbnail manager already calculated that closest match, but the storage key was still
built from the raw requested dimensions.

This caused requests such as 1000x1000 and 1920x1920 to create separate cache files even when both resolved to the
same configured thumbnail size.

Root Cause

SimpleManager.Generate calculated the closest configured resolution:

match = s.resolutions.ClosestMatch(r.Resolution, inputDimensions)

But the request resolution was not updated before building the cache key:

thumbnail, err := r.Generator.Generate(match, img)
k := s.storage.BuildKey(mapToStorageRequest(r))

As a result, mapToStorageRequest(r) still used the client-requested size.

## Fix

Normalize the request resolution to the matched configured resolution before cache lookup, generation, and storage:

r.Resolution = match
if key, exists := s.checkThumbnail(r); exists {
    return key, nil
}

Also avoid serving stale arbitrary-size cache entries when configured resolutions are present.

## Verification

Tested with:

THUMBNAILS_RESOLUTIONS=16x16,32x32,64x64,128x128,256x256,384x384,512x512,768x768

Manual before/after Docker verification:

| Build | Request | Response image | Cache file |
|---|---:|---:|---|
| before fix | 1000x1000 | 768x576 | 1000x1000-fit.jpeg |
| before fix | 1920x1920 | 768x576 | 1920x1920-fit.jpeg |
| after fix | 1000x1000 | 768x576 | 768x768-fit.jpeg |
| after fix | 1920x1920 | 768x576 | reused 768x768-fit.jpeg |

## Tests

Added unit tests covering:

- generation stores thumbnails under the matched configured resolution
- repeated arbitrary-size requests reuse the matched configured cache key
- stale non-configured cache keys are ignored when configured resolutions exist

Verified with libvips enabled:

go test -tags enable_vips ./services/thumbnails/pkg/...

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 9, 2026

@MrCodeEU MrCodeEU closed this May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant