From e78b40e4d58a124841e062dfe8a978997713461c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Fri, 23 Oct 2026 14:21:41 +0200 Subject: [PATCH] Keep the thumbnail cache apart from the old thumbnails The cache keys changed, so the old files were never read again but stayed mixed in with the new ones. With the cache in its own directory the old one can be deleted. --- services/webdav/MIGRATION.md | 8 +++++--- services/webdav/README.md | 2 +- services/webdav/pkg/config/config.go | 4 ++-- services/webdav/pkg/service/v0/service.go | 7 ++++--- services/webdav/pkg/thumbnail/cache/cache.go | 6 ++++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/services/webdav/MIGRATION.md b/services/webdav/MIGRATION.md index c7925175d5..1f25dcb38a 100644 --- a/services/webdav/MIGRATION.md +++ b/services/webdav/MIGRATION.md @@ -32,7 +32,7 @@ Nothing has to be set in the single binary. The URL may also point at a real | `THUMBNAILS_RESOLUTIONS` | `WEBDAV_THUMBNAILS_RESOLUTIONS` | a ladder of edge lengths, not a list of boxes | | `THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE` | `OC_THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE` | read by webdav and the generator, which have to agree; the old name still wins over the new one in both, so drop it when setting the new one | | `THUMBNAILS_TXT_FONTMAP_FILE` | `WEBDAV_THUMBNAILS_TXT_FONTMAP_FILE` | webdav renders text before it posts | -| `THUMBNAILS_FILESYSTEMSTORAGE_ROOT` | `WEBDAV_THUMBNAILS_CACHE_DIR` | the old name is the directory that holds `files/`, the new one is the directory itself | +| `THUMBNAILS_FILESYSTEMSTORAGE_ROOT` | `WEBDAV_THUMBNAILS_CACHE_DIR` | the old name is the directory that holds `files/`, and the cache goes into `cache/` next to it; the new one is the directory itself | The thumbnail cache has to be reachable by the webdav container after the move. @@ -75,7 +75,7 @@ webdav: resolutions: ["16", "32", "2048"] max_input_image_file_size: 50MB txt_fontmap_file: /etc/opencloud/fontmap.json - cache_dir: /var/lib/opencloud/thumbnails/files + cache_dir: /var/lib/opencloud/thumbnails/cache thumbnails: thumbnail: max_input_image_file_size: 50MB @@ -98,7 +98,9 @@ source size instead. `fit-in` still never enlarges. The cache key covers the snapped box, the operation, the output format and the file's type, so the cache is cold after the update and fills again as previews are -requested. Nothing has to be deleted. +requested. It is kept in `$OC_BASE_DATA_PATH/thumbnails/cache` now. The thumbnails +the previous version wrote to `$OC_BASE_DATA_PATH/thumbnails/files` are never read +again, so that directory can be deleted. Which types a preview is announced and attempted for is one list for webdav, graph and the PROPFIND property, set through `OC_THUMBNAILS_ADDITIONAL_SOURCE_TYPES`. A type the diff --git a/services/webdav/README.md b/services/webdav/README.md index 24e14c2c09..5b5aa464d7 100644 --- a/services/webdav/README.md +++ b/services/webdav/README.md @@ -10,7 +10,7 @@ Currently, the webdav service handles request for two functionalities, which are The webdav service provides various `GET` endpoints to get the thumbnails of a file in authenticated and unauthenticated contexts. It also provides thumbnails for spaces on different endpoints. -Generated thumbnails are cached by the webdav service itself. The cache backend defaults to `file`, storing entries under `$OC_BASE_DATA_PATH/thumbnails/files` (override with `WEBDAV_THUMBNAILS_CACHE_BACKEND` and `WEBDAV_THUMBNAILS_CACHE_DIR`). Use the `s3` backend when running multiple instances behind a load balancer so they share one cache. A backend nobody can serve, an unknown name or an `s3` backend without bucket, region and credentials, fails at startup instead of serving without a cache, as long as previews are enabled. A service that is not AWS needs `WEBDAV_THUMBNAILS_CACHE_S3_ENDPOINT` too, and it is always addressed over https. The `memory` backend is bounded and drops its oldest entries; `none` disables caching on purpose. +Generated thumbnails are cached by the webdav service itself. The cache backend defaults to `file`, storing entries under `$OC_BASE_DATA_PATH/thumbnails/cache` (override with `WEBDAV_THUMBNAILS_CACHE_BACKEND` and `WEBDAV_THUMBNAILS_CACHE_DIR`). Use the `s3` backend when running multiple instances behind a load balancer so they share one cache. A backend nobody can serve, an unknown name or an `s3` backend without bucket, region and credentials, fails at startup instead of serving without a cache, as long as previews are enabled. A service that is not AWS needs `WEBDAV_THUMBNAILS_CACHE_S3_ENDPOINT` too, and it is always addressed over https. The `memory` backend is bounded and drops its oldest entries; `none` disables caching on purpose. #### Thumbnail Query String Parameters diff --git a/services/webdav/pkg/config/config.go b/services/webdav/pkg/config/config.go index 4a0b1a80aa..7882eb4d29 100644 --- a/services/webdav/pkg/config/config.go +++ b/services/webdav/pkg/config/config.go @@ -41,9 +41,9 @@ type Thumbnails struct { MaxInputFileSize string `yaml:"max_input_image_file_size" env:"OC_THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE;THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE;WEBDAV_THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE" desc:"Maximum file size of an input image a thumbnail is made of. The generator refuses a larger body, so both read the same name by default. Usable common abbreviations: [KB, KiB, MB, MiB, GB, GiB], example: 50MB" introductionVersion:"%%NEXT%%"` CacheBackend string `yaml:"cache_backend" env:"WEBDAV_THUMBNAILS_CACHE_BACKEND" desc:"Cache backend for imagor thumbnails: 'none', 'memory', 'file', or 's3'. Default: file." introductionVersion:"%%NEXT%%"` - CacheDir string `yaml:"cache_dir" env:"WEBDAV_THUMBNAILS_CACHE_DIR" desc:"Directory for file-based thumbnail cache (Default: $OC_BASE_DATA_PATH/thumbnails/files). Only used when WEBDAV_THUMBNAILS_CACHE_BACKEND is 'file'." introductionVersion:"%%NEXT%%"` + CacheDir string `yaml:"cache_dir" env:"WEBDAV_THUMBNAILS_CACHE_DIR" desc:"Directory for file-based thumbnail cache (Default: $OC_BASE_DATA_PATH/thumbnails/cache). Only used when WEBDAV_THUMBNAILS_CACHE_BACKEND is 'file'." introductionVersion:"%%NEXT%%"` // kept so a deployment that configured the thumbnails service keeps its cache - FilesystemStorageRoot string `yaml:"filesystemstorage_root" env:"THUMBNAILS_FILESYSTEMSTORAGE_ROOT" desc:"Directory the thumbnails service stored its files in. Read as a fallback for WEBDAV_THUMBNAILS_CACHE_DIR." introductionVersion:"1.0.0" deprecationVersion:"%%NEXT%%" removalVersion:"%%NEXT_PRODUCTION_VERSION%%" deprecationInfo:"THUMBNAILS_FILESYSTEMSTORAGE_ROOT is deprecated. The webdav service owns the thumbnail cache now, so use WEBDAV_THUMBNAILS_CACHE_DIR instead." deprecationReplacement:"WEBDAV_THUMBNAILS_CACHE_DIR"` + FilesystemStorageRoot string `yaml:"filesystemstorage_root" env:"THUMBNAILS_FILESYSTEMSTORAGE_ROOT" desc:"Directory the thumbnails service stored its files in. Read as a fallback for WEBDAV_THUMBNAILS_CACHE_DIR, which is then its cache subdirectory." introductionVersion:"1.0.0" deprecationVersion:"%%NEXT%%" removalVersion:"%%NEXT_PRODUCTION_VERSION%%" deprecationInfo:"THUMBNAILS_FILESYSTEMSTORAGE_ROOT is deprecated. The webdav service owns the thumbnail cache now, so use WEBDAV_THUMBNAILS_CACHE_DIR instead." deprecationReplacement:"WEBDAV_THUMBNAILS_CACHE_DIR"` Resolutions []string `yaml:"resolutions" env:"THUMBNAILS_RESOLUTIONS;WEBDAV_THUMBNAILS_RESOLUTIONS" desc:"Allowed thumbnail edge lengths, like 512. Each axis of a requested size is rounded up to the next one of these before the box is sent to the generator. Legacy WidthxHeight entries are still accepted and contribute both of their sides, each capped at 2048, the largest box the built-in generator accepts by default." introductionVersion:"%%NEXT%%"` CacheS3Bucket string `yaml:"cache_s3_bucket" env:"WEBDAV_THUMBNAILS_CACHE_S3_BUCKET" desc:"S3 bucket name for thumbnail cache when WEBDAV_THUMBNAILS_CACHE_BACKEND is 's3'." introductionVersion:"%%NEXT%%"` CacheS3Region string `yaml:"cache_s3_region" env:"WEBDAV_THUMBNAILS_CACHE_S3_REGION" desc:"S3 region for thumbnail cache when WEBDAV_THUMBNAILS_CACHE_BACKEND is 's3'." introductionVersion:"%%NEXT%%"` diff --git a/services/webdav/pkg/service/v0/service.go b/services/webdav/pkg/service/v0/service.go index 8308a79616..23de426436 100644 --- a/services/webdav/pkg/service/v0/service.go +++ b/services/webdav/pkg/service/v0/service.go @@ -194,11 +194,12 @@ func newThumbnailWorkflow(conf *config.Config, sourceTypes thumbnail.SourceTypes // the new setting wins, the deprecated one is the fallback, and an empty // result lets the cache use its own default directory. The old setting named - // the root the thumbnails service kept a files/ directory in, so that - // deployment's thumbnails are still found where they were written. + // the root the thumbnails service kept a files/ directory in. The cache goes + // next to it, not into it, because nothing in files/ is read again and that + // directory can then be deleted as a whole. cacheDir := conf.Thumbnails.CacheDir if cacheDir == "" && conf.Thumbnails.FilesystemStorageRoot != "" { - cacheDir = filepath.Join(conf.Thumbnails.FilesystemStorageRoot, "files") + cacheDir = filepath.Join(conf.Thumbnails.FilesystemStorageRoot, "cache") } c, err := cache.NewThumbnailCache(conf.Thumbnails.CacheBackend, cacheDir, s3cfg) diff --git a/services/webdav/pkg/thumbnail/cache/cache.go b/services/webdav/pkg/thumbnail/cache/cache.go index 23c01a8420..980bbbcc16 100644 --- a/services/webdav/pkg/thumbnail/cache/cache.go +++ b/services/webdav/pkg/thumbnail/cache/cache.go @@ -13,9 +13,11 @@ import ( var ErrCacheMiss = errors.New("thumbnail cache miss") // DefaultFileCacheDir is the on-disk location of file-backend thumbnails: -// $OC_BASE_DATA_PATH/thumbnails/files. +// $OC_BASE_DATA_PATH/thumbnails/cache. It is not the files directory the old +// thumbnails service wrote to: the keys changed, nothing in there is read again, +// and keeping the two apart lets that directory be deleted as a whole. func DefaultFileCacheDir() string { - return filepath.Join(defaults.BaseDataPath(), "thumbnails", "files") + return filepath.Join(defaults.BaseDataPath(), "thumbnails", "cache") } // ThumbnailCache provides cached storage for generated thumbnails.