Generate smaller versions of design images when new versions are uploaded
Problem to solve
When design images are uploaded we should generate smaller versions of those images that can be used when displaying thumbnails.
This is still up for discussion - but as a proposal:
- a new
mediumsize for viewing designs on the discussion board
- a new
thumbnailsize for displaying designs in discussion notes
It's possible that we could skip
thumbnail and just generate a
medium, and size it down with CSS if that is more optimal.
The exact dimensions of the new size(s) should be determined with the help of UX and front-end engineers.
Generating smaller design images
As all design images are saved as LfsObject and use the
LfsObjectUploader resizing using
Carrierwave would be a natural fit.
Note, we will want to avoid generating the images within the Rails request. See https://gitlab.com/gitlab-org/gitlab-ce/issues/65163 where involving workhorse in the GraphQL design upload process is being worked on, and the uploads development guide which discusses workhorse uploads. Generating the thumbs may possibly happen as a Sidekiq job after workhorse has uploaded the file.
Original proposal (resizing without Carrierwave)
All of the below was written before it was pointed out that we could use Carrierwave to resize the images. I'm leaving it here in case it is valuable somehow!
We currently save the full-size design images directly to the design repository using LFS, with the
SaveDesignsService. After this service has generated a new
Version record, a worker should be queued to generate the smaller versions asynchronously which will also be saved to LFS.
All images within a single
Version (which represents a commit of multiple designs) should be resized to a particular size all together in order for them to committed to the repository in a single commit. That commit sha can then be recorded on the
Version record in a new
Note: If there is a concern around the memory usage of a worker resizing up to 100s of images at a time, we may need to do something like: Resize images in batches and generate a
LfsObject for each resized image using
FileTransformer#new_file. The content of the resulting LFS pointer files could be persisted somewhere temporarily (like Redis). When all the batches are resized, then all pointer files are retrieved and the commit performed.
Note: We'd need to check whether resizing files in the workers created temporary files on the worker servers and whether those files are cleaned up automatically.
Until the sizes were generated,
DesignsController#show would need to display a static placeholder image when the blob is missing.
Exposing smaller design images
DesignsController#show should be changed to take an optional
:size param and return the image at that size.
GraphQL should be updated to expose the URIs to the smaller design sizes.
Using the smaller design images
The design board and discussion notes should be updated to use the smaller design images.
Images are never deleted as previous versions of designs can be viewed.