繁体   English   中英

同步不同Sidekiq线程的方法并等待

[英]Synchronise a method different Sidekiq threads and wait

问题:我有多个sidekiq线程和一个函数,一次只能从任何线程中调用一次。

原因:我们正在查询AdWords API以获取一些数据。 当涉及到速率限制时,它们是非常严格的。 线程中只有一个可以调用该函数一次获取数据。

现在一些代码:

# Public: Get estimates for a set of keywords. If there is an error, retry
# several times. If not successful, raise an error
#
# keywords: The keyword objects to get estimates for.
# save: Boolean to indicate whether the keyword objects should be saved to
# the database
#
def repeatedly_try_get_estimates(keywords: [], save: true, sleep_delay: 150)
  return keywords if keywords.empty?
  func = -> { get_estimates(keywords, !save) }
  retry_operation(function: func, max_tries: 15, sleep_delay: sleep_delay)
end
  • 如您所见,现在我在解决该问题方面有大量的sleep_delay工作。
  • 该代码以get_estimates函数为参数调用retry_operation函数。 然后get_estimates多次重试get_estimates函数,直到出现API异常。

retry_function

# Private: Retry a function X times and wait X seconds. If it does not work X times,
# raise an error. If successful return the functions results.
#
# - max_tries: The maximum tries to repeat the function
# - sleep_delay: The seconds to wait between each iteration.
# - function: The lambda function to call each iteration
#
def retry_operation(max_tries: 5, sleep_delay: 30, function: nil, current_try: 0, result: nil)

  # Can't call, no function
  if function.nil?
    return
  end

  # Abort, tried too frequently.
  if current_try > max_tries
    raise "Failed function too often"
  end

  # Check if there is an exception
  exception = true
  begin
    result = function.call
    exception = false
  rescue => e
    Rails.logger.info "Received error when repeatedly calling function #{e.message.to_s}"
  end

  if exception
    sleep sleep_delay if sleep_delay > 0
    retry_operation(max_tries: max_tries, sleep_delay: sleep_delay, function: function, current_try: current_try + 1)
  else
    result
  end
end

get_estimates_function在这里: https : get_estimates_function 太长了,以防万一。

我想我需要执行以下操作:

  1. 调整repeatedly_try_get_estimates函数中的代码。
  2. 在类中使用互斥锁。
  3. 如果正在使用互斥锁,请拯救异常。
  4. 仅当互斥锁可用时,才运行rety_operation ,否则请休眠一段时间

谢谢你的帮助 :)

现在我们开始工作了:

# Public: Get estimates for a set of keywords. If there is an error, retry
# several times. If not successful, raise an error
#
# keywords: The keyword objects to get estimates for.
# save: Boolean to indicate whether the keyword objects should be saved to
# the database
#
def repeatedly_try_get_estimates(keywords: [], save: true, sleep_delay: 40)
  return keywords if keywords.empty?
  func = -> { get_estimates(keywords, save_keywords: true) }
  exception = nil
  result = nil
  initial_sleep = 0

  estimates_mutex.synchronize do
    since_last_request = Time.now.to_i - last_adwords_api_request
    if since_last_request <= 30
      Rails.logger.info "AdWords: Last request was only few seconds ago - sleeping #{since_last_request}."
      initial_sleep = since_last_request
    end
    begin
      result = retry_operation(function: func, max_tries: 15, sleep_delay: sleep_delay, initial_sleep: initial_sleep)
    rescue => e
      exception = e
    end
    @@last_adwords_api_request = Time.now.to_i
  end
  if exception
    raise exception
  end
  result
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM