Shrine is working flawlessly except for one thing: after the record is created with the data, it is not calling the promote code.
The upload happens and the image just stays there as cached. I monitor Sidekiq and nothing happens. The Shrine::Attacher.promote block is never called (check below).
require "shrine/storage/s3"
s3_options = {
access_key_id: ENV.fetch("S3_ACCESS_KEY_ID"),
secret_access_key: ENV.fetch("S3_SECRET_ACCESS_KEY"),
region: ENV.fetch("S3_REGION"),
bucket: ENV.fetch("S3_BUCKET"),
}
Shrine.plugin :activerecord
Shrine.plugin :direct_upload
Shrine.plugin :backgrounding
Shrine::Attacher.promote do |data|
Rails.logger.info "NEVER CALLED"
::Images::PromoteJob.perform_async(data)
end
Shrine::Attacher.delete do |data|
::Images::DeleteJob.perform_async(data)
end
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
store: Shrine::Storage::S3.new(prefix: "store", **s3_options),
}
# app/models/media_file.rb
class MediaFile < ActiveRecord::Base
include FileUploader[:file]
# ...
end
# app/uploaders/file_uploader.rb
class FileUploader < Shrine
end
# app/controllers/api/files_controller.rb
::MediaFile.create(file_data: metadata.to_json)
In the console, calling the following code promotes it. However, it does not do it via Sidekiq, it just processes it for a second without scheduling a job.
#<MediaFile:0x007fdae85e9ed8> {
:id => 23,
:file_data => "{\"id\":\"b9800404be5e39c1c7f79cebc572a93f.jpg\",\"storage\":\"cache\",\"metadata\":{\"size\":\"189404\",\"filename\":\"my-image.jpg\",\"mime_type\":\"image/jpeg\"}}",
:created_at => Tue, 16 May 2017 23:04:37 -03 -03:00,
:updated_at => Tue, 16 May 2017 23:04:37 -03 -03:00
}
[2] pry(main)> ::MediaFile.last.file_attacher.promote
MediaFile Load (0.5ms) SELECT "media_files".* FROM "media_files" ORDER BY "media_files"."id" DESC LIMIT 1
MediaFile Load (0.4ms) SELECT "media_files".* FROM "media_files" WHERE "media_files"."id" = $1 ORDER BY "media_files"."id" ASC LIMIT 1 [["id", 23]]
(0.2ms) BEGIN
SQL (0.4ms) UPDATE "media_files" SET "file_data" = $1, "updated_at" = $2 WHERE "media_files"."id" = $3 [["file_data", "{\"id\":\"5438a3969e508cd0e81ed09d89df1520.jpg\",\"storage\":\"store\",\"metadata\":{\"size\":\"189404\",\"filename\":\"my-image.jpg\",\"mime_type\":\"image/jpeg\"}}"], ["updated_at", "2017-05-17 02:05:12.853253"], ["id", 23]]
(1.2ms) COMMIT
#<FileUploader::UploadedFile:0x007fdae85b9350 @data={"id"=>"5438a3969e508cd0e81ed09d89df1520.jpg", "storage"=>"store", "metadata"=>{"size"=>"189404", "filename"=>"my-image.jpg", "mime_type"=>"image/jpeg"}}>
I don't know where to look at. Do you have any idea what's going on? Where should I start looking to figure out the problem?
Thanks a lot
You need to assign the attachment via the Shrine attribute, which is #file in your case.
::MediaFile.create(file: metadata.to_json)
#file_data is just an column attribute generated by your ORM, Shrine doesn't detect any changes to that column. That helps Shrine to be more ORM-agnostic, and it allows users to use the ORM column directly if they wish to bypass Shrine callbacks.
As for the second part of the question, Shrine::Attacher#promote will always be synchronous, regardless of whether you have backgrounding set up or not. This is needed because the Shrine::Attacher.promote method that you call inside the background job calls Shrine::Attacher#promote internally.
To spawn a background job use Shrine::Attacher#_promote. That method will just delegate to Shrine::Attacher#promote if backgrounding plugin is not loaded, but if backgrounding plugin is loaded it will call the registered block.
::MediaFile.last.file_attacher._promote
Thanks, good eye. Gonna test tonight.
Most helpful comment
You need to assign the attachment via the Shrine attribute, which is
#filein your case.#file_datais just an column attribute generated by your ORM, Shrine doesn't detect any changes to that column. That helps Shrine to be more ORM-agnostic, and it allows users to use the ORM column directly if they wish to bypass Shrine callbacks.As for the second part of the question,
Shrine::Attacher#promotewill always be synchronous, regardless of whether you have backgrounding set up or not. This is needed because theShrine::Attacher.promotemethod that you call inside the background job callsShrine::Attacher#promoteinternally.To spawn a background job use
Shrine::Attacher#_promote. That method will just delegate toShrine::Attacher#promoteifbackgroundingplugin is not loaded, but ifbackgroundingplugin is loaded it will call the registered block.