mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 11:44:49 +08:00
PERF: stop downloading images from post processor and lean on uploads
Previously we would unconditionally fetch all images via HTTP to grab original sizing from cooked post processor in 2 different spots. This was wasteful as we already calculate and cache this info in upload records. This also simplifies some specs and reduces use of mocks.
This commit is contained in:
parent
45f3e9f19e
commit
755ca0fcbb
|
@ -153,14 +153,21 @@ class CookedPostProcessor
|
|||
src = img["src"]
|
||||
return if src.blank? || is_a_hyperlink?(img) || is_svg?(img)
|
||||
|
||||
original_width, original_height = (get_size(src) || [0, 0]).map(&:to_i)
|
||||
if original_width == 0 || original_height == 0
|
||||
Rails.logger.info "Can't reach '#{src}' to get its dimension."
|
||||
return
|
||||
end
|
||||
|
||||
upload = Upload.get_from_url(src)
|
||||
|
||||
original_width, original_height = nil
|
||||
|
||||
if (upload.present?)
|
||||
original_width = upload.width || 0
|
||||
original_height = upload.height || 0
|
||||
else
|
||||
original_width, original_height = (get_size(src) || [0, 0]).map(&:to_i)
|
||||
if original_width == 0 || original_height == 0
|
||||
Rails.logger.info "Can't reach '#{src}' to get its dimension."
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if (upload.present? && upload.animated?) || src.match?(GIF_SOURCES_REGEXP)
|
||||
img.add_class("animated")
|
||||
end
|
||||
|
|
|
@ -45,10 +45,7 @@ module CookedProcessorMixin
|
|||
oneboxed_images.each do |img|
|
||||
next if img["src"].blank?
|
||||
|
||||
src = img["src"].sub(/^https?:/i, "")
|
||||
parent = img.parent
|
||||
img_classes = (img["class"] || "").split(" ")
|
||||
link_classes = ((parent&.name == "a" && parent["class"]) || "").split(" ")
|
||||
|
||||
if respond_to?(:process_hotlinked_image, true)
|
||||
still_an_image = process_hotlinked_image(img)
|
||||
|
@ -183,7 +180,13 @@ module CookedProcessorMixin
|
|||
|
||||
return unless is_valid_image_url?(absolute_url)
|
||||
|
||||
@size_cache[url] = FastImage.size(absolute_url)
|
||||
upload = Upload.get_from_url(absolute_url)
|
||||
if upload && upload.width && upload.width > 0
|
||||
@size_cache[url] = [upload.width, upload.height]
|
||||
else
|
||||
@size_cache[url] = FastImage.size(absolute_url)
|
||||
end
|
||||
|
||||
rescue Zlib::BufError, URI::Error, OpenSSL::SSL::SSLError
|
||||
# FastImage.size raises BufError for some gifs, leave it.
|
||||
end
|
||||
|
|
|
@ -21,6 +21,16 @@ Fabricator(:upload) do
|
|||
extension "png"
|
||||
end
|
||||
|
||||
Fabricator(:large_image_upload, from: :upload) do
|
||||
width 2000
|
||||
height 2000
|
||||
after_create do |upload, _transients|
|
||||
file = file_from_fixtures("2000x2000.png")
|
||||
upload.url = Discourse.store.store_upload(file, upload)
|
||||
upload.sha1 = Upload.generate_digest(file)
|
||||
end
|
||||
end
|
||||
|
||||
Fabricator(:image_upload, from: :upload) do
|
||||
transient color: "white"
|
||||
|
||||
|
|
BIN
spec/fixtures/images/2000x2000.png
vendored
Normal file
BIN
spec/fixtures/images/2000x2000.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -271,7 +271,6 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
|||
post = Fabricate(:post, raw: "<img src='#{url}'>")
|
||||
upload.update(access_control_post: Fabricate(:post))
|
||||
FileStore::S3Store.any_instance.stubs(:store_upload).returns(upload.url)
|
||||
FastImage.expects(:size).returns([100, 100]).at_least_once
|
||||
|
||||
expect { Jobs::PullHotlinkedImages.new.execute(post_id: post.id) }
|
||||
.to change { Upload.count }.by(1)
|
||||
|
@ -374,7 +373,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
|||
post.rebake!
|
||||
post.reload
|
||||
|
||||
expect(post.cooked).to match(/<img src=.*\/uploads/)
|
||||
expect(post.cooked).to match(/<img src=.*\/uploads.*\ class="thumbnail/)
|
||||
expect(post.upload_references.count).to eq(1)
|
||||
end
|
||||
|
||||
|
@ -418,7 +417,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
|||
MD
|
||||
|
||||
expect(post.cooked).to match(/<p><img src=.*\/uploads/)
|
||||
expect(post.cooked).to match(/<img src=.*\/uploads.*\ class="thumbnail"/)
|
||||
expect(post.cooked).to match(/<img src=.*\/uploads.*\ class="thumbnail/)
|
||||
expect(post.cooked).to match(/<span class="broken-image/)
|
||||
expect(post.cooked).to match(/<div class="large-image-placeholder">/)
|
||||
end
|
||||
|
@ -542,12 +541,10 @@ RSpec.describe Jobs::PullHotlinkedImages do
|
|||
end
|
||||
|
||||
describe "with a lightboxed image" do
|
||||
fab!(:upload) { Fabricate(:upload) }
|
||||
fab!(:upload) { Fabricate(:large_image_upload) }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
FastImage.expects(:size).returns([1750, 2000]).at_least_once
|
||||
OptimizedImage.stubs(:resize).returns(true)
|
||||
Jobs.run_immediately!
|
||||
end
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ require "file_store/s3_store"
|
|||
|
||||
RSpec.describe CookedPostProcessor do
|
||||
fab!(:upload) { Fabricate(:upload) }
|
||||
fab!(:large_image_upload) { Fabricate(:large_image_upload) }
|
||||
let(:upload_path) { Discourse.store.upload_path }
|
||||
|
||||
describe "#post_process" do
|
||||
|
@ -764,7 +765,6 @@ RSpec.describe CookedPostProcessor do
|
|||
end
|
||||
|
||||
it "won't remove the original image if another post doesn't have an image" do
|
||||
FastImage.stubs(:size)
|
||||
topic = post.topic
|
||||
|
||||
cpp.post_process
|
||||
|
@ -781,8 +781,7 @@ RSpec.describe CookedPostProcessor do
|
|||
end
|
||||
|
||||
it "generates thumbnails correctly" do
|
||||
FastImage.expects(:size).returns([1750, 2000])
|
||||
|
||||
# image size in cooked is 1500*2000
|
||||
topic = post.topic
|
||||
cpp.post_process
|
||||
topic.reload
|
||||
|
@ -941,17 +940,13 @@ RSpec.describe CookedPostProcessor do
|
|||
describe "#convert_to_link" do
|
||||
fab!(:thumbnail) { Fabricate(:optimized_image, upload: upload, width: 512, height: 384) }
|
||||
|
||||
before do
|
||||
CookedPostProcessor.any_instance.stubs(:get_size).with(upload.url).returns([1024, 768])
|
||||
end
|
||||
|
||||
it "adds lightbox and optimizes images" do
|
||||
post = Fabricate(:post, raw: "![image|1024x768, 50%](#{upload.short_url})")
|
||||
|
||||
post = Fabricate(:post, raw: "![image|1024x768, 50%](#{large_image_upload.short_url})")
|
||||
cpp = CookedPostProcessor.new(post, disable_dominant_color: true)
|
||||
cpp.post_process
|
||||
|
||||
doc = Nokogiri::HTML5::fragment(cpp.html)
|
||||
|
||||
expect(doc.css('.lightbox-wrapper').size).to eq(1)
|
||||
expect(doc.css('img').first['srcset']).to_not eq(nil)
|
||||
end
|
||||
|
@ -1001,7 +996,7 @@ RSpec.describe CookedPostProcessor do
|
|||
it "optimizes images in quotes" do
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
[quote]
|
||||
![image|1024x768, 50%](#{upload.short_url})
|
||||
![image|1024x768, 50%](#{large_image_upload.short_url})
|
||||
[/quote]
|
||||
MD
|
||||
|
||||
|
@ -1016,7 +1011,7 @@ RSpec.describe CookedPostProcessor do
|
|||
it "optimizes images in Onebox" do
|
||||
Oneboxer.expects(:onebox)
|
||||
.with("https://discourse.org", anything)
|
||||
.returns("<aside class='onebox'><img src='#{upload.url}' width='512' height='384'></aside>")
|
||||
.returns("<aside class='onebox'><img src='#{large_image_upload.url}' width='512' height='384'></aside>")
|
||||
|
||||
post = Fabricate(:post, raw: "https://discourse.org")
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user