处理批量长api调用的最佳实践

时间:2015-01-16 02:06:32

标签: javascript jquery ruby ajax ruby-on-rails-4

我设计了一个用户界面,用于上传用户列表(电子邮件,姓名等),在此过程结束时,每个用户都插入了我的数据库并收到了一封电子邮件

处理此任务的后端api是在rails上的ruby中构建的。

目前对输入的大小没有限制,因此我想为UI用户提供一种在整个上传过程中取消剩余作业的方法,而不取消已经发送的作业。

我还希望在GUI上提供正在处理作业的实时状态,已经完成。

此外,我想确保生成的同时处理作业的作业数量有限,以便服务器上的其他用户不会受到影响。

有了这个......并且我的有限的后端/ javascript知识,我想我会做的是为每个用户(或者可能是几个用户的分组)产生单独的ajax调用,使用java来限制任何用户时间只有X ajax调用可以同时运行(我希望这是可能的),当每次调用返回时,我将更新UI以反映作业的状态,然后为下一组作业生成另一个,直到整件事情都完成了。如果UI用户希望取消,他们可以使完成的作业保持完整。

这是可取的还是有更好的方法来做到这一点。

提前致谢

1 个答案:

答案 0 :(得分:0)

我使用sidekiq来完成这样的任务。它完全符合您的需求。

您设置了许多工作程序,这些工作程序是服务器上的线程。然后,当POST或其他请求从UI进入时,您将每个请求排队作为sidekiq中的作业,并立即将状态返回到浏览器,因此他们不必等待,想知道是否会发生某些事情成功,永远挂起,或通过网络服务器获得超时。

稍后,作业将异步处理。它可以更新数据库中的状态以进行报告。

以下是在sidekiq下运行的worker的示例:

class PageFetcher
  include Sidekiq::Worker

  def perform page_id
    page = Page.find(page_id)
    path = Page.absolute_path

    # Do some big, long, error-prone thing with external depencies:
    File.binwrite(path, open(page.source_url).read)
    saved_size = File.size(path)

    if page.expected_file_size != saved_size.to_s
      bad_path = path + '.bad'
      File.rename(path, bad_path)

      # Raise an error, and sidekiq will automatically wait a while and try again later:
      raise IOError, "Could not cache #{page.source_url} to #{path}. " +
        "File size is #{saved_size}, expected #{page.file_size}. "
    end


    # update some status field, so this success can be reported:
    page.make_status_cached!

    # do something else that depends on this success:
    page.notify_page_indexer
  end
end

当您收到新请求时,请创建一个新页面,然后将其处理排队如下:

Page.perform_async(self.id)

瞧!那就是它。