在heroku上通过sidekiq导入csv时的file.path问题

Don*_*nMB 6 ruby-on-rails heroku sidekiq

我正在使用后台作业将用户数据从 csv 文件导入到我的数据集中。首先,我在用户模型中通过简单地调用用户模型中的方法并传递通过表单传输的文件路径来“硬”执行此操作file_field

\n\n
User.import_csv(params[:file].path)\n
Run Code Online (Sandbox Code Playgroud)\n\n

在本地和生产环境中运行良好(heroku)。

\n\n

现在,当涉及到巨大的 CSV 文件时,我明白我需要一份工作来在后台执行此导入。我熟悉 redis 和 sidekiq,所以这个工作很快就完成了。

\n\n
CsvImportJob.perform_async(URI.parse(params[:file].path))\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的工人中:

\n\n
def perform(file_path)\n\n  User.import_csv(file_path)\n\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

嗯,这在本地也很完美,但是当我在生产中遇到这个问题时,我在日志中看到以下错误:

\n\n
\xc2\xbb 10 Aug 2015 13:56:26.596 2015-08-10 11:56:25.987726+00:00 app worker.1 - - 3 TID-oqvt6v1d4 ERROR: Actor crashed!\n\xc2\xbb 10 Aug 2015 13:56:26.596 2015-08-10 11:56:25.987728+00:00 app worker.1 - - Errno::ENOENT: No such file or directory @ rb_sysopen - /tmp/RackMultipart20150810-6-14u804c.csv\n\xc2\xbb 10 Aug 2015 13:56:26.596 2015-08-10 11:56:25.987730+00:00 app worker.1 - - /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/csv.rb:1256:in `initialize\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

这意味着是file_path变量。\n不知何故,当我将文件传递给 sidekiq 作业时,heroku 无法找到该文件。当我在没有 sidekiq 的情况下执行此操作时,它可以工作。

\n\n

我真的不知道如何解决这个问题,因此非常感谢您的帮助。

\n

Rav*_*ven 1

我有同样的经历,你可以看看我的类似项目:https://github.com/coderaven/datatable-exercise/tree/parallel_processing

(基本上只关注 object_record.rb 模型和作业:import_csv_job.rb 和 process_csv_job.rb)

错误: Errno::ENOENT: No such file or directory @ rb_sysopen 如果您说这适用于 heroku 那么可能意味着您获得的路径是有效的(在您的示例中您使用的是 /tmp/ 路径)

所以这里有两个可能的问题及其解决方案:

1.) 您保存了 Heroku 未知的路径(或不可访问的路径),应用程序在运行时无法访问或打开该路径。因为,在不使用 sidekiq 的情况下处理导入 csv 时 - 您上传的文件会暂时保存在内存中,直到您完成处理 csv - 但是,在作业调度程序(或 sidekiq)中,路径不应该在内存中,而应该是现有路径该应用程序可以访问该内容。

解决方案:将文件保存到某个存储中(heroku 有一个临时文件系统,因此您无法通过正在运行的 Web 应用程序保存文件)要解决此问题,您必须使用类似 Amazon S3 的服务(您也可以使用 Google Drive,例如我这样做了)将您的文件保存在那里,然后将路径提供给您的 sidekiq 工作人员 - 以便它稍后可以访问和处理它。

2.) 如果路径正确并且文件保存或处理正确,那么根据我的经验,您可能使用的是 File.open 而不是 open-uri 的 open 方法。File.open 不接受远程文件,您需要在工作线程上要求 open-uri,然后使用 open 方法来解决远程文件问题。

前任。

require 'open-uri'

class ProcessCsvJob < ActiveJob::Base
  queue_as :default

  def perform(csv_path)
    csv_file = open(csv_path,'rb:UTF-8')

    SmarterCSV.process(csv_file) do |array|
        .... code here for processing ...
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

我完全意识到这个问题已经过去了将近一年,所以如果您已经解决了这个问题或者这个答案有效,那么它也可以帮助作为那些可能会遇到同样问题的人的文档存档。