0

我在做什么

我在我的应用程序中使用了twitter gem(Twitter API 的 Ruby 包装器),该应用程序在Heroku上运行。我使用Heroku 的调度程序定期运行缓存任务,这些任务使用 twitter gem 来更新特定用户的转发列表。我也在使用delayed_job,所以调度程序调用了一个rake任务,它调用了一个“延迟”的方法(参见下面的scheduler.rake)。该方法循环通过“身份验证”(对于通过我的应用程序对 twitter 进行身份验证的用户)来更新每个授权用户在应用程序中的转发缓存。

我的问题

我在做什么例如,由于我使用的是 Heroku 的调度程序,delayed_job 是多余的吗?此外,您可以看到我没有发现(拯救)任何错误。因此,如果 Twitter 无法访问,或者用户的身份验证令牌已过期,那么一切都会阻塞。这显然是愚蠢和可怕的,因为如果出现错误,整个事情就会窒息并最终创建一个失败的延迟作业,这会给我的应用程序带来连锁反应。我可以看到这很糟糕,但我不确定最好的解决方案是什么。我应该如何/在哪里发现错误?

我将把我的所有代码(从调度程序到被调用的方法)放在我的一个缓存方法中。我真的只是希望有一个项目符号列表(可能还有一些代码或伪代码)来谴责我糟糕的编码实践并告诉我在哪里可以改进。

我已经看到了这个 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”方法中找到了所有“twitter”身份验证,然后调用“User.twitter”方法,该方法专门限制为“twitter”身份验证。这显然是多余的,我会修复它。

4

1 回答 1

1

首先你得到的确切错误是什么,当出现错误时你想发生什么?

编辑:

如果您只想捕获错误并记录它们,那么以下应该可以工作。

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 做这样的事情会更好,然后尝试自己处理每个错误。我从 twitter API 中看到了很多奇怪的东西,以及随机错误,以至于试图追踪每一个错误几乎总是会变成一场疯狂的追逐,尽管为了以防万一,保持追踪仍然是件好事。


接下来是什么时候应该使用什么。

当您需要仅基于时间发生某些事情时,您应该使用调度程序,当它基于用户操作时延迟作业,但是您要延迟的“操作”将需要很长时间才能获得正常响应。有时你也可以把东西简单地放在控制器中。

所以换句话说

只要更新X之间的时间小于更新发生的时间Y ,调度程序就可以了。

如果X < Y那么您可能希望查看在访问每个单独的条目时从控制器调用逻辑,而不是尝试一次完成所有操作。这个想法是你只会在经过一段时间后更新它。您可以将最后一次更新存储在模型本身的 twitter_udpate_time 之类的字段中,也可以存储在 redis 或 memecache 实例中的用户/身份验证键处。

但是,如果单个更新本身仍然太长,那么您应该执行上述操作,而不是执行实际更新,而是调用延迟作业。

您甚至可以将其设置为仅在一定数量的视图后更新或调用延迟的作业,以进一步限制内容。

可能的花式裤子

或者,如果您想变得非常花哨,您仍然可以将其作为一项 cron 工作来完成,但有一个基于视图的点系统,该系统对哪些条目应该更新的权重进行加权。某些操作的想法会为某些用户添加积分,如果他们的积分超过一定数量,您更新他们,然后删除他们的积分。这样您就可以定位您认为最重要的那些,或者拥有最多的流量或出现在最多的搜索结果中等等。


接下来是尼克挑剔的事情。

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

你应该使用

@authentications.find_each do |authentication|

代替

@authentications.each do |authentication|

find_each 一次只提取 1000 个条目,因此如果您最终获得大量身份验证,您最终不会将大量条目拉入内存。

于 2013-04-05T18:08:10.937 回答