'How can I keep temporary file even use ActiveJob Async

I have a simple upload file process and throw to background job (sidekiq) on Rails 5.2.6. I'm using ActionDispatch::Http::UploadedFile to store the file as temporary file. The temporary file will be unlink once the HTTP request is completed.

https://api.rubyonrails.org/v5.2.6/classes/ActionDispatch/Http/UploadedFile.html

Uploaded files are temporary files whose lifespan is one request. When the object is finalized Ruby unlinks the file, so there is no need to clean them with a separate maintenance task.

So I want to keep the temporary file and read it on background job as asynchronous even the HTTP request is completed in controller stage

Controller

def upload
  UploadFileJob.perform_later(params[:file_uploads].path)
  redirect_to root_path
end

Job

class UploadFileJob < ActiveJob::Base
  def perform(file_path)
    sheet = Roo::Spreadsheet.open(file_path)
  end
end

The issue is when background job is running, that can't read the file because the file was removed (the HTTP request is completed).

2022-02-09T07:17:33.756Z pid=24902 tid=gqdvonm4i class=UploadFileJob jid=e8262af8c41e83f22ad06149 INFO: Adding dead ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper job e8262af8c41e83f22ad06149
2022-02-09T07:17:33.757Z pid=24902 tid=gqdvonm4i class=UploadFileJob jid=e8262af8c41e83f22ad06149 elapsed=0.009 INFO: fail
2022-02-09T07:17:33.757Z pid=24902 tid=gqdvonm4i WARN: {"context":"Job raised exception","job":{"retry":true,"queue":"default","class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","wrapped":"UploadFileJob","args":[{"job_class":"UploadFileJob","job_id":"0143f401-ddc8-4db8-9e77-32048eb7de4a","provider_job_id":null,"queue_name":"default","priority":null,"arguments":["/tmp/RackMultipart20220209-25523-ltyki7.xlsx"],"executions":0,"locale":"id"}],"jid":"e8262af8c41e83f22ad06149","created_at":1644391053.7475002,"enqueued_at":1644391053.7475615},"jobstr":"{\"retry\":true,\"queue\":\"default\",\"class\":\"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper\",\"wrapped\":\"UploadFileJob\",\"args\":[{\"job_class\":\"UploadFileJob\",\"job_id\":\"0143f401-ddc8-4db8-9e77-32048eb7de4a\",\"provider_job_id\":null,\"queue_name\":\"default\",\"priority\":null,\"arguments\":[\"/tmp/RackMultipart20220209-25523-ltyki7.xlsx\"],\"executions\":0,\"locale\":\"id\"}],\"jid\":\"e8262af8c41e83f22ad06149\",\"created_at\":1644391053.7475002,\"enqueued_at\":1644391053.7475615}"}
2022-02-09T07:17:33.758Z pid=24902 tid=gqdvonm4i WARN: IOError: file /tmp/RackMultipart20220209-25523-ltyki7.xlsx does not exist
2022-02-09T07:17:33.758Z pid=24902 tid=gqdvonm4i WARN: /var/www/html/application/shared/bundle/ruby/2.6.0/gems/roo-2.7.1/lib/roo/base.rb:398:in `local_filename'

Is there anyway to do that only use ActionDispatch without use ActiveStorage or something else, I mean can I keep the file until the background job is done while the request is completed in controller side?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source