【问题标题】:Implement caching in Sinatra app to handle twitter rate limits在 Sinatra 应用程序中实现缓存以处理 twitter 速率限制
【发布时间】:2014-02-25 20:52:48
【问题描述】:

我编写了一个小型 Sinatra 脚本来获取用户的 2 条推文,并按其编号的降序显示 10 位转发者。追随者:

拼图/puzzle.rb

require 'twitter'
require 'json'
require 'sinatra'
#require 'haml'

client = Twitter::REST::Client.new do |config|
    config.consumer_key        = ""
    config.consumer_secret     = ""
    config.access_token        = ""
    config.access_token_secret = ""
end

set :server, 'webrick'

set :haml, :format => :html5

get '/' do
  content_type :json
  arr = []
        retweeters = client.retweeters_of(429627812459593728)

        retweeters.each do |retweeter|
            ob = {}
            ob[:name] = retweeter.name
            ob[:followers_count] = retweeter.followers_count
            arr.push(ob)
        end


    # remove the duplicates and sort on the users with the most followers,
    sorted_influencers = arr.sort_by { |hsh| hsh[:followers_count] }
    sorted_influencers.reverse!
    sorted_influencers[0..9].to_s
end

我正在尝试处理速率限制。

如何缓存json输出以避免超出速率限制?

【问题讨论】:

    标签: ruby caching twitter sinatra rate-limiting


    【解决方案1】:

    假设您保持非常简单的场景,您可以使用一个小的自定义类来存储信息并提供线程安全的方法(从您的问题中不清楚您的问题到底在哪里,但无论如何都会出现这个问题) :

    require 'json'
    require 'sinatra'
    require 'date'
    require 'thread'
    require 'twitter'
    
    set :server, 'webrick'
    
    set :haml, :format => :html5
    
    class MyCache
      def initialize()
        @mutex = Mutex.new
        @last_update = DateTime.new            # by default, -4732 BC
        @client = Twitter::REST::Client.new do |config|
          config.consumer_key        = ""
          config.consumer_secret     = ""
          config.access_token        = ""
          config.access_token_secret = ""
        end
      end
    
      def get_cache
        @mutex.synchronize do
          if DateTime.now - @last_update > 10.0 / (3600 * 24)
            @last_update = DateTime.now
    
            arr = []
            retweeters = @client.retweeters_of(429627812459593728)
    
            retweeters.each do |retweeter|
              ob = {}
              ob[:name] = retweeter.name
              ob[:followers_count] = retweeter.followers_count
              arr.push(ob)
            end
    
            # remove the duplicates and sort on the users with the most followers,
            sorted_influencers = arr.sort_by { |hsh| hsh[:followers_count] }
            sorted_influencers.reverse!
            @cache = sorted_influencers[0..9].to_s
          end
    
          @cache
        end
      end
    end
    
    my_cache = MyCache.new
    
    get '/' do
      content_type :json
      my_cache.get_cache
    end
    

    此版本现在包含所需的一切。我使用@client 来存储twitter 客户端的实例(我想它是可重用的),还要注意整个代码是如何在if 语句中的,最后我们更新@cache。如果你不熟悉 Ruby,一个块的值是由它的最后一个表达式决定的,所以当我单独写@cache 时,就好像我写了return @cache

    【讨论】:

    • 我编辑了我的代码,向您展示了如何从路由中调用它。关于 Sinatra,您必须了解的一件事是每个请求都将位于一个新的“实例”上下文中,因此当您在路由中使用实例变量时,它们不会持续到下一次调用(如果您有两个用户调用同一个页面,实例变量明显不同)。
    • 为什么我会收到这个错误 <class:MyCache>': undefined method get' for MyCache:Class (NoMethodError) ?
    • 我编辑了我的答案以获得一个完整的工作代码,我也忘记更新@last_update,但现在它已经正确完成了。如果你运行它,你会看到一个新的时间戳,但只有每十秒一次。插入您自己的代码来查询 twitter API 应该只在 if 子句中。
    • 感谢@user846250!它每 10 秒提供一次所需的输出,也避免了速率限制。但是有一个问题,如果我在 10 秒之前重新加载网页,它会给出一个错误 undefined method `sort_by' for nil:NilClass。请纠正我我哪里错了。更新要点您可以使用这些 twitter 凭据在本地执行它。
    • 我使用您的原始变量名称更新了代码,如果您想知道代码的特定部分,我认为您应该考虑打开一个新问题(另外,您的问题可能已经被问过,所以考虑先搜索)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 2020-10-04
    • 2014-08-05
    • 1970-01-01
    相关资源
    最近更新 更多