Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Pass Tempfile to Sidekiq

I work on a mailing endpoint that gathers attachments as a Tempfile, then I need to pass them to a Sidekiq Worker to upload them to AWS.

My problem is that I'm stuck at the point I'm trying to persist the Tempfile and then open it in my worker. I don't know with what I should open my Tempfile (path, filename...).

Here is my function that will call the worker:

if @email
    # Remove Tempfile autodelete
    @email.attachments.each {|t| ObjectSpace.undefine_finalizer(t.tempfile)}

    # Griddler Email to hash for Sidekiq
    email = {
        attachments: @email.attachments.map {|att| {
            type: att.content_type,
            name: att.original_filename
        }},
        raw_text: @email.raw_text,
        raw_html: @email.raw_html,
        from: @email.from,
        subject: @email.subject,
        to: @email.to,
        cc: @email.cc
    }

    EmailResponseWorker.perform_async email
end

Here I use ObjectSpace.undefine_finalizer(t.tempfile) to disable auto delete.

Then in my Sidekiq Worker:

def perform(email)
  @email = email

  attachments = @email['attachments'].inject([]) do |arr, file|
    object = S3_BUCKET.objects["attachments/#{SecureRandom.uuid}/#{file['name']}"].write(Tempfile.open(file['name']), acl: :public_read)
    arr << {url: object.public_url.to_s, type: file['type'], name: file['name']}
  end
end

Here attachments['name'] is the name of the file.

like image 621
Ismael Bourg Avatar asked Apr 20 '16 17:04

Ismael Bourg


1 Answers

Get path from the tempfile and handle it as a usual file path:

path: att.tempfile.path

it is path to the tempfile itself, original_filename is the filename passed by client, not the one you need.

Do not forget to unlink it after the job has completed successfully.

like image 58
Vasfed Avatar answered Nov 01 '22 04:11

Vasfed