2013-04-05 10 views
0

Что я делаюЛовля ошибок с использованием Ruby Twitter gem, методы кэширования с использованием delayed_job: Что я делаю неправильно?

Я использую twitter gem (оболочку Ruby, для API Twitter) в мое приложение, которое запускается на Heroku. Я использую Heroku's Scheduler, чтобы периодически запускать задачи кэширования, которые используют твиттер, чтобы, например, обновить список ретвитов для определенного пользователя. Я также использую delayed_job, поэтому планировщик вызывает задачу рейка, которая вызывает метод «delayed» (см. Scheduler.rake ниже). Этот метод проходит через «аутентификации» (для пользователей, прошедших проверку подлинности через мое приложение), чтобы обновить кеш-ретвит в каждом авторизованном пользователе в приложении.

Мой вопрос

Что я делаю неправильно ? Например, поскольку я использую планировщик Heroku, избыточность delayed_job? Кроме того, вы можете видеть, что я не ловил (спасая) любые ошибки. Итак, если Twitter недоступен, или если токен авторизации пользователя истек, все задыхается. Это очевидно глупо и страшно, потому что, если есть ошибка, вся штука задыхается и заканчивается тем, что создает неудавшееся delayed_job, что вызывает эффект пульсации для моего приложения. Я вижу, что это плохо, но я не уверен, какое лучшее решение. Как/где я должен ловить ошибки?

Я поместил весь свой код (от планировщика до вызываемого метода) для одного из моих методов кэширования. Я действительно надеюсь, что для маркированного списка (и, возможно, кода или псевдокода) я буду ругать меня за плохую практику кодирования и сказать, где я могу улучшить ситуацию.

Я видел this SO question, что немного помогает мне с блоком начала и спасения, но я мог бы использовать больше рекомендаций по ошибкам ловушки, а один более высокий уровень «это хороший способ сделать это?». самолет.

Код

Heroku Планировщик работы:

rake update_retweet_cache 

scheduler.rake (в мое приложение)

task :update_retweet_cache => :environment do 
    Tweet.delay.cache_retweets_for_all_auths 
end 

Tweet.rb, update_retweet_cache метод:

def self.cache_retweets_for_all_auths 
    @authentications = Authentication.find_all_by_provider("twitter") 

    @authentications.each do |authentication| 
    authentication.user.twitter.retweeted_to_me(include_entities: true, count: 200).each do |tweet| 
     # Actually build the cache - this is good - removing to keep this short 
    end 
    end 
end 

User.rb, метод твиттера:

def twitter 
    authentication = Authentication.find_by_user_id_and_provider(self.id, "twitter") 
    if authentication 
    @twitter ||= Twitter::Client.new(:oauth_token => authentication.oauth_token, :oauth_token_secret => authentication.oauth_secret) 
    end 
end 

Примечание: Как я отправляю это, я заметил, что я нахожу все «щебет» аутентификации в «cache_retweets_for_all_auths» метод, затем вызывая «User .twitter ", который специально ограничивает аутентификацию" twitter ". Это явно избыточно, и я исправлю это.

ответ

1

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

Edit:

Если вы просто хотите, чтобы поймать ошибки и зарегистрировать их, то должно работать.

def self.cache_retweets_for_all_auths 
    @authentications = Authentication.find_all_by_provider("twitter") 

    @authentications.each do |authentication| 
    being 
     authentication.user.twitter.retweeted_to_me(include_entities: true, count: 200).each do |tweet| 
     # Actually build the cache - this is good - removing to keep this short 
     end 
    rescue => e 
     #Either create an object where the error is log, or output it to what ever log you wish. 
    end 
    end 
end 

Таким образом, когда он не работает, он будет продолжать переход к следующему пользователю, но все равно заметит ошибку. Большую часть времени с твиттером просто лучше сделать что-то подобное, а затем попытаться сделать с каждой ошибкой самостоятельно. Я видел так много странных вещей из twitter API, и случайные ошибки, которые пытаются отследить каждую ошибку, почти всегда превращаются в дикую погоню за гусями, хотя по-прежнему хорошо отслеживать на всякий случай.


Далее, если вы должны использовать что.

Вы должны использовать планировщик, когда вам нужно что-то произойти, основанное только на времени, отложенные задания, когда оно основано на действии пользователя, но «действие», которое вы собираетесь отложить, потребует длительного ответа. Иногда вы также можете просто добавить вещь в контроллер.

Так другими словами

планировщик будет хорошо до тех пор, как время между обновлениями X меньше, то время, которое потребуется для обновления произойдет, время Y.

Если X < Y, то вы можете захотеть взглянуть на вызов логики от контроллера, когда каждый indvidual вход доступен, isntead попытки сделать их все сразу. Идея заключается в том, что вы только обновите ее через определенное время, пройдя так. Вы могли сохранить последнее обновление времени либо в самой модели в поле типа twitter_udpate_time, либо в экземпляре redis или memecache с ключом unquie для пользователя/auth.

Но если само индивидуальное обновление слишком длинное, то тогда, когда вы должны сделать выше, но вместо фактического обновления вызовите задержанное задание.

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

Возможного Fancy Pants

Или, если вы хотите получить действительно фантазию вы все еще могли бы сделать это как хроны, но имеешь балльную систему на основе представлений, вес, какие элементы должны быть обновлены. Идея, состоящая в определенных действиях, добавила бы точки определенным пользователям, и если их очки превысят определенную сумму, вы их обновите, а затем удалите их очки. Таким образом, вы могли предназначаться теми, которые вы считаете наиболее важными, или имеют наибольший трафик или отображаться в большинстве результатов поиска и т.д. и т.п.


Следующих от ника разборчива вещь.

http://api.rubyonrails.org/classes/ActiveRecord/Batches.html

Вы должны использовать

@authentications.find_each do |authentication| 

вместо

@authentications.each do |authentication| 

find_each тянет только 1000 записей в то время, так что если вы в конечном итоге с МВУ авторизаций вы не 't в конечном итоге тянет сумасшедшее количество записей в память.

+0

Привет - спасибо за отличный ответ! Во-первых, я не уверен, в чём ошибка, о которой я боюсь, потому что прошло некоторое время с тех пор, как я получил ее. Вот почему я думаю: «Ну, почему бы не просто убедиться, что я ЛЮБЛЮ ошибку от Twitter, чтобы она не бомбила вещи?» Как только я начну видеть ошибки, которые были пойманы, я могу получить более подробный/точный. – JoshDoody

+0

Далее я должен сказать, что причина, по которой я использую job/delayed_job, заключается в том, что обновления кеша занимают довольно много времени. Иногда задание выполняется в течение нескольких минут (даже для одного пользователя). Поэтому я периодически создаю кеш (скажем, один раз в час) и удаляя старые записи один раз в день. Таким образом, при загрузке сводной страницы (которая использует данные Twitter) не происходит задержки, и мой кеш не становится огромным. Наконец, ваш «должен быть, а не» блок показывает одно и то же дважды. Но мне очень интересно видеть ваше предложение. Не могли бы вы исправить это? – JoshDoody

+0

жаль, что, должно быть .find_each вместо .each. Будет обновлен ответ за секунду. – rovermicrover