Shrine::Attacher.promote { |data| Shrine::PromoteWorker.perform_in(30.seconds, data) }Vips::Error: VipsForeignLoad: "/tmp/shrine-s320190512-12411-1jfqxfo.jpg" is not a known file formatprocess(:store) do |io, context|
versions = { printable: io } # retain original
io.download do |original|
pipeline = ImageProcessing::Vips.source(original)
versions[:mobile_index] = pipeline.resize_to_limit!(768, 768, sharpen: false) # Full-width. # <---- EXCEPTION ALWAYS OCCURS HERE
versions[:index] = pipeline.resize_to_limit!(360, 360, sharpen: false) # 2 up on tablet, 3 up on desktop
# Watermark example
# https://groups.google.com/d/msg/ruby-shrine/6v6dMVG-ygs/LxEbXw5YCAAJ
#
watermark = host_logo_file(context)
versions[:shareable] = pipeline
.resize_to_limit(1200, 1200, sharpen: false)
.composite(watermark, # Set the watermark as the overlay image
mode: "over", # Apply the watermark 'over' the source (default)
gravity: "south-east", # Apply the watermark in the bottom right corner
offset: [55, 55], # Apply the watermark 55 pixels up and left from ':gravity' setting
)
.call # Apply operation
watermark.close!
end
versions # return the hash of processed files
end$ ls -1 /tmp/
image_processing20190505-29621-109gfjd.jpg
image_processing20190505-29621-15q8swz.jpg
image_processing20190505-29621-1c7psbu.jpg
def generate_location(io, context)
default_unique_identifier = [context[:version], super].compact.join('-')
client_id = context[:record].client_id
appointment_id = context[:record].appointment_id
# Keep in sync with Shrine.storages[:cache].presign (UploadableAppointment#upload_details)
['clients', client_id, 'appointments', appointment_id, 'images', default_unique_identifier].join('/')
endprocess(:store) do |io, _|
versions = { original: io }
io.download do |original|
pipeline = ImageProcessing::MiniMagick.source(original)
versions[:medium] = pipeline.resize_to_limit!(700, 700)
versions[:small] = pipeline.resize_to_limit!(400, 400)
versions[:thumb] = pipeline.resize_to_limit!(200, 200)
versions[:square] = pipeline.resize_to_fill!(100, 100)
end
versions
endprocess(:store) do |io, _|
versions = { original: io }
io.download do |original|
pipeline = ImageProcessing::MiniMagick.source(original)
versions[:medium] = pipeline.resize_to_limit!(700, 700)
versions[:small] = pipeline.resize_to_limit!(400, 400)
versions[:thumb] = pipeline.resize_to_limit!(200, 200)
versions[:square] = pipeline.resize_to_fill!(100, 100)
end
versions
end
process(:store) do |io, _|
original = io.download
pipeline = ImageProcessing::Vips.source(original)
medium = pipeline.resize_to_limit!(700, 700)
small = pipeline.resize_to_limit!(400, 400)
thumb = pipeline.resize_to_limit!(200, 200)
square = pipeline.resize_to_fill!(100, 100)
original.close!
{ original: io, medium: medium, small: small, thumb: thumb, square: square }
endShrine.plugin :logging, logger: Rails.logger
Shrine.plugin :cached_attachment_data
Shrine.plugin :upload_options
Shrine.plugin :activerecordplugin :delete_promoted
plugin :determine_mime_type
plugin :infer_extension, inferrer: :mini_mime
plugin :processing
plugin :store_dimensions, analyzer: :ruby_vips
plugin :validation_helpers
plugin :versions
plugin :backgrounding
plugin :data_uri
plugin :determine_mime_type
plugin :delete_promoted
plugin :infer_extension, inferrer: :mini_mime
plugin :processing
plugin :store_dimensions, analyzer: :ruby_vips
plugin :upload_options, store: (lambda do |_io, _context|
{ acl: 'public-read' }
end)
plugin :validation_helpers
plugin :versionsgem 'aws-sdk-s3', '~> 1.40.0'
gem 'image_processing', '~> 1.9.0'
gem 'ruby-vips', '~> 2.0.13'
gem 'shrine', '~> 2.17.1'Hi Jess,No sorry I haven't had a chance, I've been kinda swamped in other areas. I'm starting to raise my head above the parapet this week though so will make time this week and give it a go.DaveOn Sun, 14 Jul 2019 at 08:08, Jess Latham <jesse....@gmail.com> wrote:Hi Dave,Just checking in to see if you've made any headway here with Janko's suggestion of replacing io.download?Cheers,JessOn Wed, Jun 19, 2019 at 4:13 PM Dave Harris <da...@harris.org.nz> wrote:Hi Jess,Yeah replacing io.download with the code above is something that I can do relatively easily. I still don't know how it's triggered so I will just have to wait for a busy time and see if it happens again.I should probably add the delete_raw plugin too. That might explain the reason why it runs out of hard drive space.I'll let you know how I get on.DaveOn Thu, 20 Jun 2019 at 05:36, Jess Latham <jesse....@gmail.com> wrote:Thanks for the insight @Janko Marohnić! It's something approachable that I could try here as well.Dave - what do you think? Anything ringing a bell here?Cheers guys,JessOn Sat, Jun 15, 2019 at 2:53 PM Janko Marohnić <janko.m...@gmail.com> wrote:Thanks for all the details, sorry for the late response.First of all, the VipsForeignLoad error does sound like the file could be corrupted. When Shrine downloads the file to disk, it closes the file descriptor to force a flush and then opens it again. So, from the perspective of IO system buffers we should be good.However, S3#open (which Shrine::UploadedFile#download eventually calls) internally uses Down::ChunkedIO to wrap S3's streaming, which could theoretically have a bug, or maybe just in conjunction with aws-sdk-s3. I would recommend trying downloading only with aws-sdk-s3 (avoiding Down::ChunkedIO) and see whether that resolves the issue. So, you could replace `io.download` with:
process(:store) do |io, _|
original = Tempfile.new(["shrine", ".#{io.extension}"], binmode: true)object = io.storage.object(io.id)object.get(response_target: original)original.open # refresh file descriptor, which forces flush# ...endAlternatively, if you're locking to Down 4.8.0, you could try downgrading to 4.7.0. 4.8.0 introduced a security measure which unlinks Down::ChunkedIO's internal Tempfile. But it should work fine, because I stole that trick from Rack and Unicorn, which are pretty battle tested.Some other notes from the discussion:
- `io.download` with a block ensures the Tempfile is deleted even in case of exceptions
- without `delete_raw` plugin the processed files won't get deleted after uploading (Ruby's GC should theoretically delete Tempfiles which aren't used anymore, but it's known to take its sweet time)
- `store_dimensions` plugin swallows any Vips::Error exceptions, so it could be that dimensions are blank because a Vips::Error has happened (unfortunately Shrine doesn't log these exceptions yet, but it's in my TODO list)
Kind regards,JankoOn 11 Jun 2019, 00:50 +0200, Jess Latham <jesse....@gmail.com>, wrote:
Hey Dave,Sorry man, apologies for not getting back to you sooner. Thanks for bubbling back up and the extra details you've just provided.I had not yet had a chance to put together a dummy project to try and repro the issue here. Unfortunately got a small team and I'm trying to help move some big pieces through at the moment and so don't have spare cycles available to properly experiment and put together a production-level test case. :(For my own experience it's really interesting that on my side that I have two separate products/environments and they're behaving differently due to some possibly low level configuration (one successful and one unsuccessful).I wonder if @Janko Marohnić has any insights here to what we're experiencing? Maybe some interesting bits had come up during implementation on his side?Maybe we'll see what he says and regroup afterwards?Cheers,Jess
--
You received this message because you are subscribed to a topic in the Google Groups "Shrine" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ruby-shrine/KmlmMVO6f-Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ruby-shrine...@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/0ccaebb5-1d21-4b76-9950-2b597a83c507%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine...@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/CAPRTHQgOaU6vLXszkdjZPnM%2B7cxnufyJ%3DMX_OE0wioBks6pLbw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/CAPRTHQgZf7Bmf5c-LfHpZ6vtnqd8hqxg7WPuS96qkjvy9RH1Bw%40mail.gmail.com.