我有一个Rails应用程序,它有一个带有标志available
的Document
。文档被上传到外部服务器,在那里无法立即获得(需要时间来传播)。我想做的是轮询可用性,并在可用时更新模型。
我正在为这个过程寻找性能最好的解决方案(服务不提供回调):
Document
已上传到应用程序- 应用程序上载到外部服务器
- 应用程序轮询url(http://external.server.com/document.pdf)直到可用
- 应用程序更新模型Document.available=true
我被困在3号。我已经在我的项目中使用sidekiq了。这是一种选择吗,还是我应该使用一种完全不同的方法(cron作业)。
Documents
将一直被上传,因此首先轮询数据库/redis以检查不可用的Documents
似乎是相关的。
看到这个答案:在Ruby 中发出超时的HTTP HEAD请求
基本上,您为已知的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
这仍然是一个阻塞操作。如果您尝试联系的服务器速度较慢或没有响应,则打开Net::HTTP连接将被阻止。如果你担心,就用伤寒。有关详细信息,请参阅以下答案:在Ruby中执行非阻塞I/O的首选方式是什么?