2013-06-25 9 views
1

У меня есть приложение для рельсов, работающее на Heroku. Я пытаюсь добавить функцию, которая позволяет пользователям загружать некоторые из своих данных в формате CSV. Файлы CSV являются большими (~ 1-2 МБ), и они медленно генерируются. Чтобы не связывать свои веб-диноды, я передаю запрос на загрузку на рабочие динамики (используя Resque) и собираю CSV. Мой рабочий-реск выглядит примерно так.Как отправить данные клиенту от работника-спасателя?

class Downloader 

    def self.perform(ids_to_download) 
     models = Model.where(:id => ids_to_download) 
     csv_data_for_client = models.to_csv 
    end 

end 

Мне интересно, как лучше отправить файл csv клиенту, который его запросил.

Если этот код был в контроллере Rails, это может быть выполнено просто с send_data csv_data_for_client. Тем не менее, этот подход, похоже, не работает из рабочего Resque.

От исследования SO и в других местах в Интернете, кажется, у меня есть несколько вариантов.

  1. Отправьте данные непосредственно из рабочего Resque (Хотя я не уверен, если это возможно)
  2. Сохранить данные в Heroku файловой системы, восстановить его в контроллере, а затем отправить его с send_data
  3. Сохраните его в базу данных (PostgreSQL), получить его в контроллере, а затем использовать send_data

Может кто-нибудь дать советы на лучший способ продолжить? Благодарю.

ответ

0

После выполнения некоторого мышления, устранил варианты 1 и 2.

Re 1, я не мог понять, как отправить файл CSV непосредственно клиенту от работника Resque.

Re 2, сохраняя файл csv в Heroku, также не представляется возможным. Документы Heroku говорят, что each dyno has its own filesystem, и эта файловая система видна только для того, кто ее владеет. Мой рабочий динамо не может читать или писать в файловую систему моего веб-динода, и наоборот. Так что это не похоже на многообещающий вариант.

Это оставило мне вариант 3, сохранив файл csv в моей базе данных в моем рабочем динамо, а затем извлекая его и отправив его клиенту в моем веб-дино.

Я использовал жемчужину resque-status, чтобы назначить уникальный идентификатор (uuid) для каждого запроса файла csv.

Я создал простую модель для хранения сгенерированного файла csv и связал его с его uuid.

class DownloaderJobOutput < ActiveRecord::Base 
    attr_accessible :file_to_download, :uuid 
end 

В моем рабочем работнике resque после создания файла csv я сохранил его в своей базе данных.

class Downloader 
    @queue = :trial_downloader_queue 
    include Resque::Plugins::Status 

    def perform 
    models = Model.where(:id => options["trial_ids"]) 
    csv = models.to_csv 
    DownloaderJobOutput.create!(:uuid => self.uuid, :file_to_download => csv) 
    end 
end 

В то время как работа выполнялась, я опросил ее со своего веб-клиента, чтобы отслеживать ее статус. Когда он будет завершен, я вытащил его из базы данных и отправлю его клиенту.

+0

Просто загрузите с помощью Paperclip и, если он настроен для загрузки на S3, он также должен сохранить ссылку на файл в базе данных. Я так старался, что он работает как шарм. –

+0

Huh. Круто. Я никогда не слышал о Паперклипе. Я посмотрю. –