diff --git a/app/models/alchemy/picture/url.rb b/app/models/alchemy/picture/url.rb index e33f14e3ad..c819c74d1a 100644 --- a/app/models/alchemy/picture/url.rb +++ b/app/models/alchemy/picture/url.rb @@ -3,7 +3,7 @@ module Alchemy class Picture < BaseRecord class Url - attr_reader :variant + attr_reader :variant, :thumb # @param [Alchemy::PictureVariant] # @@ -31,14 +31,23 @@ def processible_image? def uid signature = PictureThumb::Signature.call(variant) - thumb = variant.picture.thumbs.detect { |t| t.signature == signature } - if thumb - uid = thumb.uid + if find_thumb_by(signature) + thumb.uid else uid = PictureThumb::Uid.call(signature, variant) - PictureThumb.generator_class.call(variant, signature, uid) + ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do + PictureThumb.generator_class.call(variant, signature, uid) + end + uid end - uid + end + + def find_thumb_by(signature) + @thumb = if variant.picture.thumbs.loaded? + variant.picture.thumbs.find { |t| t.signature == signature } + else + variant.picture.thumbs.find_by(signature: signature) + end end end end diff --git a/app/models/alchemy/picture_thumb/create.rb b/app/models/alchemy/picture_thumb/create.rb index fff38f83ea..0334f4e4c3 100644 --- a/app/models/alchemy/picture_thumb/create.rb +++ b/app/models/alchemy/picture_thumb/create.rb @@ -19,11 +19,10 @@ def call(variant, signature, uid) # create the thumb before storing # to prevent db race conditions - thumb = Alchemy::PictureThumb.create!( - picture: variant.picture, - signature: signature, - uid: uid, - ) + @thumb = Alchemy::PictureThumb.create_or_find_by!(signature: signature) do |thumb| + thumb.picture = variant.picture + thumb.uid = uid + end begin # process the image image = variant.image @@ -32,7 +31,7 @@ def call(variant, signature, uid) rescue RuntimeError => e ErrorTracking.notification_handler.call(e) # destroy the thumb if processing or storing fails - thumb&.destroy + @thumb&.destroy end end diff --git a/spec/models/alchemy/picture/url_spec.rb b/spec/models/alchemy/picture/url_spec.rb index 65f969d1f9..6a8914fe22 100644 --- a/spec/models/alchemy/picture/url_spec.rb +++ b/spec/models/alchemy/picture/url_spec.rb @@ -34,5 +34,11 @@ it "returns the url to the thumbnail" do is_expected.to match(/\/pictures\/\d+\/.+\/image\.png/) end + + it "connects to writing database" do + writing_role = ActiveRecord::Base.writing_role + expect(ActiveRecord::Base).to receive(:connected_to).with(role: writing_role) + subject + end end end diff --git a/spec/models/alchemy/picture_thumb/create_spec.rb b/spec/models/alchemy/picture_thumb/create_spec.rb index 8f02c43b10..92ced8e392 100644 --- a/spec/models/alchemy/picture_thumb/create_spec.rb +++ b/spec/models/alchemy/picture_thumb/create_spec.rb @@ -15,6 +15,20 @@ expect { create }.to change { variant.picture.thumbs.reload.length }.by(1) end + context "with a thumb already existing" do + let!(:thumb) do + Alchemy::PictureThumb.create!( + picture: picture, + signature: "1234", + uid: "/pictures/#{picture.id}/1234/image.png", + ) + end + + it "does not create a new thumb" do + expect { create }.to_not change { picture.thumbs.reload.length } + end + end + context "with an invalid picture" do let(:picture) { FactoryBot.build(:alchemy_picture) }