From 994ef16b72478c3c33f81466a13b77ef4fee5ebb Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 9 Aug 2024 14:48:34 +0200 Subject: [PATCH] Bust CDN cache on media deletion (#31353) --- app/models/media_attachment.rb | 28 ++++++++++++++++++++++++++++ spec/models/media_attachment_spec.rb | 19 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index f53da04a975..a9470e1ad20 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -276,6 +276,9 @@ class MediaAttachment < ApplicationRecord before_create :set_unknown_type before_create :set_processing + before_destroy :prepare_cache_bust!, prepend: true + after_destroy :bust_cache! + after_commit :enqueue_processing, on: :create after_commit :reset_parent_cache, on: :update @@ -410,4 +413,29 @@ class MediaAttachment < ApplicationRecord def reset_parent_cache Rails.cache.delete("v3:statuses/#{status_id}") if status_id.present? end + + # Record the cache keys to burst before the file get actually deleted + def prepare_cache_bust! + return unless Rails.configuration.x.cache_buster_enabled + + @paths_to_cache_bust = MediaAttachment.attachment_definitions.keys.flat_map do |attachment_name| + attachment = public_send(attachment_name) + styles = DEFAULT_STYLES | attachment.styles.keys + styles.map { |style| attachment.path(style) } + end + rescue => e + # We really don't want any error here preventing media deletion + Rails.logger.warn "Error #{e.class} busting cache: #{e.message}" + end + + # Once Paperclip has deleted the files, we can't recover the cache keys, + # so use the previously-saved ones + def bust_cache! + return unless Rails.configuration.x.cache_buster_enabled + + CacheBusterWorker.push_bulk(@paths_to_cache_bust) { |path| [path] } + rescue => e + # We really don't want any error here preventing media deletion + Rails.logger.warn "Error #{e.class} busting cache: #{e.message}" + end end diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 3142b291fb2..3297387ff72 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -292,6 +292,25 @@ RSpec.describe MediaAttachment, :attachment_processing do end end + describe 'cache deletion hooks' do + let(:media) { Fabricate(:media_attachment) } + + before do + allow(Rails.configuration.x).to receive(:cache_buster_enabled).and_return(true) + end + + it 'queues CacheBusterWorker jobs' do + original_path = media.file.path(:original) + small_path = media.file.path(:small) + thumbnail_path = media.thumbnail.path(:original) + + expect { media.destroy } + .to enqueue_sidekiq_job(CacheBusterWorker).with(original_path) + .and enqueue_sidekiq_job(CacheBusterWorker).with(small_path) + .and enqueue_sidekiq_job(CacheBusterWorker).with(thumbnail_path) + end + end + private def media_metadata