2013-02-22 3 views
0

У меня есть приложение, в котором пользователи будут загружать файлы непосредственно на S3. Это работает. Теперь мне нужен фоновый работник (в настоящее время delayed_job), чтобы извлечь файл и занести его в «tmp/files» для обработки.Как приложение Rails загружает файл с S3?

Как это можно сделать?

Редакции: приложение в настоящее время работает в EC2.

+0

Вы используете Heroku? EC2? – Stpn

+0

EC2. Отредактированный вопрос. Благодарю. – n8gard

+0

помогли ли ответы? – Stpn

ответ

0

Фоновые работники будут работать независимо от вашего веб-приложения.

Попробуйте Resque для широко используемого решения для рабочего стола Rails. Идея состоит в том, что вы начинаете Resque независимо от своего веб-приложения, и он выполняет свои задания независимо от приложения.

Этот рабочий отправил базовые HTTP-запросы на S3. Вот вам API reference card, чтобы вы начали. Идея заключается в том, что вы используете какой-то клиент Ruby REST для отправки этих запросов и анализируете ответ, который вы получаете от S3. Rest-client - это драгоценный камень, который вы можете использовать для этого.

Возможно, у вас также может быть рабочий S3 gem, который может быть немного проще.

При таком подходе, вы бы ваш рабочий запустить скрипт, который делает что-то вроде

picture = S3Object.find 'headshot.jpg', 'photos'

+0

Это не отвечает на мой вопрос. Как у меня есть рабочий, какой бы вид, подключиться к S3 и загрузить файл? – n8gard

+0

Обновлен мой ответ. Если вам нужна дополнительная информация, дайте мне знать. Вопрос немного расплывчатый. – varatis

0

Используйте Resque.

добавить

gem 'resque' 
gem 'resque-status' 

С Resque вам нужно Redis (для хранения информации о рабочих) либо использовать Redis навынос или установить Redis локально на EC2 машине.

Таким образом, после Resque установлен редактировать конфиг/Инициализаторы/resque.rb

rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..' 
rails_env = ENV['RAILS_ENV'] || 'production' 
resque_config = YAML.load_file(rails_root + '/config/resque.yml') 
Resque.redis = resque_config[rails_env] 

    # This is if you are using Redis to go: 
    # ENV["REDISTOGO_URL"] ||= "redis://REDISTOGOSTUFFGOESHERE" 
    # uri = URI.parse(ENV["REDISTOGO_URL"]) 
    # Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :thread_safe => true) 

Resque::Plugins::Status::Hash.expire_in = (24 * 60 * 60) # 24hrs in seconds 

Dir["#{Rails.root}/app/workers/*.rb"].each { |file| require file } 

Здесь мы используем местную Redis, так resque.yml выглядит следующим образом:

development: localhost:6379 
test: localhost:6379 
fi: localhost:6379 
production: localhost:6379 

Вам нужно что-то как Бог, чтобы начать/управлять рабочими

Поэтому установите его, затем добавьте «resque-production.god» в конфигурацию/папку вашего приложения. . Вы сможете начать работу с вашими работниками с помощью этого: бога -с конфиг/спасательного-production.god конфиг/спасательного-production.god файл Willl есть что-то вроде:

rails_env = ENV['RAILS_ENV'] || "production" 
rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/..' 
num_workers = 1 

num_workers.times do |num| 
    God.watch do |w| 
    w.dir  = "#{rails_root}" 
    w.name  = "resque-#{num}" 
    w.group = 'resque' 
    w.interval = 30.seconds 
    w.env  = {"QUEUE"=>"*", "RAILS_ENV"=>"production"} 
    w.start = "rake -f #{rails_root}/Rakefile environment resque:work --trace" 
    w.log  = "#{rails_root}/log/resque.log" 
    w.err_log = "#{rails_root}/log/resque_error.log" 


    # restart if memory gets too high 
    w.transition(:up, :restart) do |on| 
     on.condition(:memory_usage) do |c| 
     c.above = 350.megabytes 
     c.times = 2 
     end 
    end 

    # determine the state on startup 
    w.transition(:init, { true => :up, false => :start }) do |on| 
     on.condition(:process_running) do |c| 
     c.running = true 
     end 
    end 

    # determine when process has finished starting 
    w.transition([:start, :restart], :up) do |on| 
     on.condition(:process_running) do |c| 
     c.running = true 
     c.interval = 5.seconds 
     end 

     # failsafe 
     on.condition(:tries) do |c| 
     c.times = 5 
     c.transition = :start 
     c.interval = 5.seconds 
     end 
    end 

    # start if process is not running 
    w.transition(:up, :start) do |on| 
     on.condition(:process_running) do |c| 
     c.running = false 
     end 
    end 
    end 
end 

Наконец работников. Они идут в приложение/рабочие/папки (здесь приложение/рабочие/processor.rb)

class Processor 
    include Resque::Plugins::Status 
    @queue = :collect_queue 

    def perform 
    article_id = options["article_id"] 
    article = Article.find(article_id) 
    article.download_remote_file(article.file_url) 
    end 
end 

Он запускается обратный вызов в модели статьи (приложение/модели/article.rb)

class Article < ActiveRecord::Base 

    after_create :process 

    def download_remote_file(url) 
    # OpenURI extends Kernel.open to handle URLs as files 
    io = open(url) 

    # overrides Paperclip::Upfile#original_filename; 
    # we are creating a singleton method on specific object ('io') 
    def io.original_filename 
     base_uri.path.split('/').last 
    end 

    io.original_filename.blank? ? nil : io 
    end  

def process 
    Processor.create(:article_id => self.id) 
    end 

end 
Смежные вопросы