Ruby on rails 构造轮询外部服务(RoR)的最佳方法

Ruby on rails 构造轮询外部服务(RoR)的最佳方法,ruby-on-rails,ruby,polling,Ruby On Rails,Ruby,Polling,我有一个Rails应用程序,它有一个文档,标记为可用。文档将上载到外部服务器,但该服务器无法立即使用(传播需要时间)。我想做的是调查可用性,并在可用时更新模型 我正在为此过程寻找性能最好的解决方案(服务不提供回调): 文档已上载到应用程序 应用程序上载到外部服务器 应用程序轮询url(),直到可用为止 app updates model Document.available=true 我被困在3号线上了。我已经在我的项目中使用了sidekiq。这是一个选项,还是我应该使用完全不同的方法(cron

我有一个Rails应用程序,它有一个
文档
,标记为
可用
。文档将上载到外部服务器,但该服务器无法立即使用(传播需要时间)。我想做的是调查可用性,并在可用时更新模型

我正在为此过程寻找性能最好的解决方案(服务不提供回调):

  • 文档
    已上载到应用程序
  • 应用程序上载到外部服务器
  • 应用程序轮询url(),直到可用为止
  • app updates model Document.available=true
  • 我被困在3号线上了。我已经在我的项目中使用了sidekiq。这是一个选项,还是我应该使用完全不同的方法(cron作业)

    文档将一直上载,因此首先轮询数据库/redis以检查不可用的
    文档似乎是相关的。

    请参阅以下答案:

    基本上,您为已知url设置一个HEAD请求,然后异步循环,直到返回200(迭代之间有5秒的延迟,或者其他)

    上载文档后,从控制器执行此操作:

    Document.delay.poll_for_finished(@document.id)
    
    然后在文档模型中:

    def self.poll_for_finished(document_id)
      document = Document.find(document_id)
      # make sure the document exists and should be polled for
      return unless document.continue_polling?
    
      if document.remote_document_exists?
        document.available = true
      else
        document.poll_attempts += 1 # assumes you care how many times you've checked, could be ignored.
        Document.delay_for(5.seconds).poll_for_finished(document.id)
      end
      document.save
    end
    
    def continue_polling?
      # this can be more or less sophisticated
      return !document.available || document.poll_attempts < 5
    end
    
    def remote_document_exists?
      Net::HTTP.start('http://external.server.com') do |http|
        http.open_timeout = 2
        http.read_timeout = 2
        return "200" == http.head(document.path).code
      end
    end
    
    def self.poll_for_finished(文档id)
    document=document.find(document\u id)
    #确保该文档存在,并应轮询以获取
    除非返回文档,否则返回。是否继续轮询?
    如果document.remote\u document\u存在?
    document.available=true
    其他的
    document.poll_尝试次数+=1#假设您关心检查了多少次,则可以忽略。
    Document.delay_为(5.秒)。poll_为_完成(Document.id)
    结束
    document.save
    结束
    def是否继续轮询?
    #这可能或多或少有些复杂
    回来!document.available | | document.poll_尝试次数<5次
    结束
    def远程文档是否存在?
    Net::HTTP.start('http://external.server.com“)do | http|
    http.open\u超时=2
    http.read_timeout=2
    返回“200”==http.head(document.path).code
    结束
    结束
    

    这仍然是一个阻塞操作。如果您试图联系的服务器速度慢或无响应,则打开Net::HTTP连接将被阻止。如果你担心的话,就用Typhous。请参阅此答案了解详细信息:

    这似乎是对Sidekiq工人的浪费。如果响应不是200,则最好使作业失败,然后稍后重试作业(例如,一分钟后)。工人可以快速前进并尝试其他文件。@davidcelis:我根据您的反馈更新了我的答案。进一步的改进可能包括缩短超时时间或切换到Tyohoeus,同时分批进行几次检查。