carrierwave_backgrounder
carrierwave_backgrounder copied to clipboard
Asset being uploaded before backgrounder gets to it on update
ruby 2.0.0-p0 Carrierwave 0.8.0 Carrierwave_backgrounder 0.2.1 Rails 4.0.0.rc1 Sidekiq 2.12.0 Redis 3.0.4 Fog 1.11.1
Using store_in_background
When I attempt to update a video:
File is uploaded to cache Record gets the tmp column updated File is uploaded to Rackspace Cloudfiles as if backgrounder wasn't being used Then sidekiq attempts to update file on Cloudfiles but can't find the resource since the file now has a new name from the upload that happened before backgrounder attempted to update the resource.
Controller update action:
def update
if @video.update(video_params)
redirect_to edit_admin_video_path(@video), notice: 'Video was successfully updated.'
else
render action: 'edit'
end
end
Uploader class:
class VideoUploader < CarrierWave::Uploader::Base
include ::CarrierWave::Backgrounder::Delay
storage :fog
def store_dir
"#{@model.class.to_s.underscore.pluralize}/#{@model.id}/#{@mounted_as.to_s}"
end
def extension_white_list
%w(mp4)
end
end
Video class:
require 'carrierwave/orm/activerecord'
class Video < ActiveRecord::Base
...
mount_uploader :file_url, VideoUploader
store_in_background :file_url
...
end
@jvsidler have you considered using the process_in_background option that backgrounder provides? I believe that I needed to enable both, to solve my problems.
Are you using any kind of custom workers around backgrounder (as I was in my issue)?
@ekampp I get a NoMethodError on 'body' for whatever reason when I enable both. Switching to process_in_background fixes the problem I'm having but times out my browser when uploading. Shouldn't it pass that to the background?
Thanks so much for your suggestion.
@jvsidler, store_in_background is the method you want to use if you want to defer processing and uploading to s3. The real question is, why is the upload not getting deferred until sidekiq processes the job.
Can you try with master?
@lardawge I'll try with master right now
@lardawge same issue still occurs. When I put a debugger in the store_dir method on my uploader it gets called three times after submitting ...
@lardawge I've put together a test app at https://github.com/jvsidler/carryup. You can verify that it is happening on a brand new app. Please let me know if there is anything I can do to help.
I'm working with resque, and I don't have any of these problems. Have you considered swapping out your queue, to determine if it's backgrounder it self, or a problem with backgrounder/sidekiq?
@jvsidler,
It looks like you have a couple issues here...
- You should name the file field without the _url suffix. It is possibly confusing carrierwave and is causing CB to not behave correctly.
- The field for storing the tmp directory should not be passed into the form. It is for CB internal use.
Something like this:
class Video < ActiveRecord::Base
mount_uploader :attachment, VideoUploader
store_in_background :attachment
end
Migration
class CreateVideos < ActiveRecord::Migration
def change
create_table :videos do |t|
t.string :attachment
t.string :attachment_tmp
t.timestamps
end
end
end
If your intention is to pass in the video as a url, the field in the form would need to be :remote_attachment_url.
@lardawge I changed the column name as you suggested but to no avail. Also, I did not have a _tmp form field in my app, I just missed that when rapidly prototyping the test app.
@ekampp I swapped sidekiq out for resque and it seems to be working ... at least on my test app.
@lardawge I'm still getting the same behavior. I've changed the column names and removed the tmp field from the form and switched to resque. Even on the test app. Can you reproduce locally with my test app?
@lardawge some more info step by step:
- I turned my worker queue OFF and created a record and, as expected, it did not upload
- I turned the queue worker ON and it uploaded successfully as expected
- I turned the queue worker OFF and updated the record. IMMEDIATELY on Rackspace Cloudfiles the whole directory from record_id down (I'm saving to model_name/record_id/mounted_on/file_name) was deleted and nothing was uploaded
- I turned my queue worker ON and the worker reports a fail because it can't find the resource BUT uploads the new file correctly. Since the job reports an error, the database record is not updated with the new file name and doesn't remove the info in the _tmp column
Can you try just assigning file_attachment?
@video.file_attachment = params[:file_attachment]
if @video.save
...
Saves immediately to rackspace and then the background job fails.
def update
@video.file_attachment = video_params[:file_attachment]
if @video.save
redirect_to @video, notice: 'Video was successfully updated.'
else
render action: 'edit'
end
end
If it works with resque, but not sidekiq, that suggests to me, that the issue is in the interface between sidekiq and backgrounder. @lardawge is there a central place, where the different worker queues are defined and handled?
@ekampp my test app is currently using resque
Ok. And the problem still persists? Strange. I don't have that problem with my app. I will try and download yours tomorrow.
@lardawge step number five from above is more accurately stated as follows:
- I turned my queue worker ON and the worker reports a failure because it can't find the resource BUT THE FILE IS UPLOADED CORRECTLY. The job reports an error so the database record is not updated with the new file name and doesn't remove the info in the _tmp column.
This is weird since the file correct file gets up there just fine ...
I'll try and have a look at it tonight...
Thanks so much!
What is the error you are seeing from the worker?
CarrierWave::Workers::StoreAsset Arguments "Video" "5" "file_attachment" Exception Fog::Storage::Rackspace::NotFound Error [HTTP 404] resource not found in ord region
I can also confirm that the upload happens before the background job attempts it because if I remove the asset from Rackspace I get the error right away. This shows me that the upload is attempted immediately. When make sure the asset is on Rackspace as my application expects it to be, the upload works fine and then the background job fails.
@jvsidler, I think there is some funkiness with rackspace cdn. I get the error just trying to submit the update form. It creates it fine but can't fins the resource on update.
But it works fine when I take carrierwave_backgrounder out ... where does backgrounder intercept the create/update calls?
I have the same problem - I believe this a bug in carrierwave: https://github.com/carrierwaveuploader/carrierwave/issues/1333
I am also using process_in_background and I am getting a lot of errors from backgrounders about not able to find a temp file, perhaps the same problem? Since it make sense if the files has been uploaded before sidekiq get a chance to process it.
E, [2015-02-21T21:17:02.258660 #16795] ERROR -- : Actor crashed!
CarrierWave::ProcessingError: Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: Command ("mogrify -resize 200x200 /tmp/mini_magick20150221-16795-4ox14p.jpg") failed: {:status_code=>nil, :output=>""}
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/processing/mini_magick.rb:273:in `rescue in manipulate!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/processing/mini_magick.rb:259:in `manipulate!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/processing/mini_magick.rb:153:in `resize_to_fit'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/processing.rb:84:in `block in process!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/processing.rb:76:in `each'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/processing.rb:76:in `process!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave_backgrounder-0.4.1/lib/backgrounder/delay.rb:14:in `process!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/callbacks.rb:18:in `block in with_callbacks'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/callbacks.rb:18:in `each'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/callbacks.rb:18:in `with_callbacks'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/cache.rb:122:in `cache!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave-0.10.0/lib/carrierwave/uploader/versions.rb:226:in `recreate_versions!'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/carrierwave_backgrounder-0.4.1/lib/backgrounder/workers/process_asset.rb:12:in `perform'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:75:in `execute_job'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:52:in `block (2 levels) in process'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:127:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/sidekiq.rb:33:in `block in call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:365:in `perform_action_with_newrelic_trace'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/sidekiq.rb:29:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-unique-jobs-3.0.11/lib/sidekiq_unique_jobs/middleware/server/unique_jobs.rb:17:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-failures-0.4.3/lib/sidekiq/failures/middleware.rb:9:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/logging.rb:11:in `block in call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/logging.rb:22:in `with_context'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/logging.rb:7:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:132:in `call'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:132:in `invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:51:in `block in process'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:98:in `stats'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:50:in `process'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
/var/www/wwm/releases/37/vendor/bundle/ruby/2.1.0/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'