Rails 3: Как вернуть большой документ JSON - PullRequest
1 голос
/ 26 июня 2011

Я хочу вернуть около 90 тыс. Элементов в документе JSON, но я получаю эту ошибку при выполнении вызова:

Timeout::Error in ApisController#api_b

time's up!
Rails.root: /root/api_b

Я просто запускаю "rails s" с сервером rails по умолчанию.

Какой способ заставить это работать и вернуть документ?

Спасибо

  @bs.each do |a|
          puts "dentro do bs.each"
          @final << {  :Email => a['headers']['to'], :At => a['date'], :subject => a['headers']['subject'], :Type => a['headers']['status'], :Message_id => a['headers']['message_id'] }
        end

Быть @bs объектом BSON из MongoDB. Тайм-аут в "@final << ..." </p>

1 Ответ

1 голос
/ 27 июня 2011

Если вы испытываете таймауты от рельсов и есть возможность кэшировать данные (например, данные изменяются нечасто), я бы сгенерировал ответ в фоновом режиме, используя resque или delayed_job и чем Rails отправляет это клиенту. Или, если данные не могут быть кэшированы, используйте легкий обработчик Rack , такой как Sinatra и Metal , чтобы генерировать ответы.

Отредактировано для отражения данных выборки

Мне удалось запустить следующий код в экземпляре Rails 3.0.9 для высокопроизводительного экземпляра Mongo 1.8.4. Я использовал Mongo 1.3.1, bson_ext 1.3.1, webrick 1.3.1 и Ruby 1.9.2p180 x64. Это не время ожидания, но потребовалось некоторое время для загрузки. Мой образец базы данных Mongo имеет 100 тыс. Записей и не содержит индексов.

before_filter :profile_start
after_filter :profile_end
  def index
    db   = @conn['sample-dbs']
    collection = db['email-test']

    @final = []
    @bs = collection.find({})
    @bs.each do |a|
      puts "dentro do bs.each"
      @final << {  :Email => a['headers']['to'], :At => a['date'], :subject => a['headers']['subject'], :Type => a['headers']['status'], :Message_id => a['headers']['message_id'] }
    end
    render :json => @final
  end

  private
    def profile_start
      RubyProf.start
    end

    def profile_end
      RubyProf::FlatPrinter.new(RubyProf.stop).print
    end

Более эффективный способ выгрузить записи -

@bs = collection.find({}, {:fields => ["headers", "date"]})
@final = @bs.map{|a| {:Email => a['headers']['to'], :At => a['date'], :subject => a['headers']['subject'], :Type => a['headers']['status'], :Message_id => a['headers']['message_id'] }}
render :json => @final

Мой генератор данных

 100000.times do |i|
   p i
   @coll.insert({:date =>Time.now(),:headers => {"to"=>"me@foo.com", "subject"=>"meeeeeeeeee", "status" => "ffffffffffffffffff", "message_id" => "1234634673"}})
 end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...