【问题标题】:Retry function on failure after x amount of time在 x 时间后重试失败的功能
【发布时间】:2018-06-29 23:12:08
【问题描述】:

问题:

我有一个通过 Cronjob 触发的函数。此 cronjob 在晚上 10:00 触发该函数,但假设不存在正确处理该函数所需的数据。我想失败,然后让函数重试 1 小时。我该如何处理这个问题?

代码:

  def check_question do
    case question = Repo.get_by(Question, active: true, closed: true) do

    question when not(is_nil(question)) ->
      case ActiveQuestion.ready_for_answer_status(conn, question) do

      end
    _ ->
      # RETRY CODE HERE
    end
  end

所以你可以从这段代码中看到。如果查询没有找到问题,我将 case 语句发送到失败,但在失败的情况下,我想在 1 小时内返回函数。如何使用 Elixir/Phoenix 实现这一目标?感谢您的帮助!

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    您可以使用 genserver 发送 msg 在 1 小时后执行 check_question

    如果服务器关闭,计时器将不会继续倒计时。

    如果给定的 dest 是 PID,计时器将自动取消 哪个不存在或给定的 PID 退出时。

    在这种情况下,self 返回调用进程的 PID(进程标识符)。

      defmodule Periodically do
        use GenServer
    
        def start_link do
          GenServer.start_link(__MODULE__, %{})
        end
    
        def init(state) do
          # DingDing.Helper.update_all_company_users()
          # One.Dingding.Auth.update_app_access_token()
          check_question()
          {:ok, state}
        end
    
        def handle_info(:update, state) do
          check_question()
          {:noreply, state}
        end
    
        def check_question do
          case question = Repo.get_by(Question, active: true, closed: true) do
    
          question when not(is_nil(question)) ->
            case ActiveQuestion.ready_for_answer_status(conn, question) do
    
            end
          _ ->
            Process.send_after(self(), :update, 60*60*1000)
          end
        end
      end
    

    【讨论】:

    • 如果服务器关闭会怎样?计时器会一直倒计时吗?
    • @Bitwise 如果服务器关闭,那要看你是否使用了supervisor。 hexdocs.pm/elixir/Supervisor.html我在回答中添加了对计时器问题的解释。
    • 感谢您的帮助!我决定为此使用 Exq 而不是 genserver。我需要确保作业在服务器崩溃后幸存下来,并且 exq 由 redis 支持,因此它为我解决了这个问题。
    • 技术上 Exq 使用 GenServer,但我决定不自己推出。 :)
    【解决方案2】:

    我更喜欢从 cron 作业将任务排入作业系统,例如 Exq(redis 支持)或 ecto_job(postgresql 支持)。

    从那里它会自动重试到某个最大值,重试之间会有延迟。

    它还具有在服务器重新启动等情况下幸存的好处。

    【讨论】:

    • 那么,当 cronjob 触发“check_question”功能时,系统会在后台将任务排入队列,然后我可以控制重试以及重试发生的时间?
    • 是的,如果数据不可用,您可以重新安排作业在给定时间运行。
    【解决方案3】:

    GenServer 的解决方案在这里对我来说似乎有点矫枉过正。我会去做一个不受监控的任务,又名Task.start/1。这种解决方案的缺点是如果任务失败,没有人会知道并且请求的操作不会生效。如果必须确保任务成功完成,请使用@yonghao-hu 提供的解决方案。

    @task fn ->
      case question = Repo.get_by(Question, ...) do
        question when not(is_nil(question)) ->
          ...
        _ ->
          Process.sleep(5_000) # delay
          Task.start(@task)
        end
    end
    

    在您的 cron 管理代码中的某处:

    Task.start @task
    

    【讨论】:

      猜你喜欢
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 2016-03-05
      • 2019-05-27
      • 2015-09-05
      • 2014-04-30
      相关资源
      最近更新 更多