I have a model Report to export all the Pdf attachments done for the bills. I have other models Bill, Upload.
Bill has many uploads
Tech Stack used
Ruby 2.5.8 Rails 5.0.7
Dummy Code
require 'fileutils'
require 'zip'
require 'open-uri'
class Report < ApplicationRecord
def to_a
main_dir = "tmp/Attachment-#{self.id}"
FileUtils::mkdir_p main_dir
bills.each do |bill|
bill_directory_name = "Bill_#{bill.id}"
bill.uploads.each do |bill_upload|
FileUtils::cd main_dir do
FileUtils::mkdir_p "#{bill_directory_name}"
file = open(bill_upload.file.url, 'rb')
upload_name = "Invoice-#{bill_upload.file_file_name}-#{bill_upload.id}"
FileUtils::cd "#{bill_directory_name}" do
IO.copy_stream(file, "#{upload_name}")
end
end
end
end
path = "tmp/Attachment-#{self.id}"
archive = File.join(path, "Attachment-#{self.id}" + '.zip')
FileUtils.rm archive, force: true
Zip::File::open(archive, 'w') do |zipfile|
Dir["#{path}/**/**"].reject{|f| f==archive }.each do |file|
zipfile.add(file.sub(path + '/', ''), file)
end
end
end
end
Task
I am creating main directory tmp/Attachment-#{self.id}. Inside it, I am creating multiple billing directories (bill_directory_name) for the bills. And inside each of the billing directories I am including uploaded invoice after reading actual invoice saved inside upload model. And Final zip folder is created, archived and downloaded.
Problem
When I execute my code only once, it works perfect.
But if I execute it multiple times in multi threading environment then it says No such file or directory.
Following are the errors
/Users/siv/.rbenv/versions/2.5.8/lib/ruby/2.5.0/fileutils.rb:122: warning: conflicting chdir during another chdir block
WARN: Errno::ENOENT: No such file or directory @ dir_chdir - test-1111-Sup-14-invoice
WARN: /Users/siv/.rbenv/versions/2.5.8/lib/ruby/2.5.0/fileutils.rb:122:in `chdir'
/Users/siv/.rbenv/versions/2.5.8/lib/ruby/2.5.0/fileutils.rb:122:in `cd'
/Users/siv/proj/app/models/report.rb:46:in `block in to_a'
Error in this line: bill.uploads.each do |bill_upload|
/Users/siv/proj/app/models/report.rb:48:in `block (2 levels) in to_a'
Error in this line: FileUtils::cd main_dir do
/Users/siv/script/proj/app/models/report.rb:55:in `block (3 levels) in to_a'
Error in this line: FileUtils::cd "#{bill_directory_name}" do
Any feedback will be appreciated.
I believe FileUtils makes use of Dir for the chdir/cd method, and while it may not be documented in FileUtils, it is documented in Dir that cd/chdir is not thread safe.
https://ruby-doc.org/core-3.1.2/Dir.html#method-c-chdir