How can I keep temporary file even use ActiveJob Async

Viewed 131

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?

0 Answers
Related