x 时间后失败时重试功能



问题:

我有一个通过 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 小时内返回函数。我怎样才能用长生不老药/凤凰来实现这一点?感谢您的帮助!

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

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

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

如果给定的目的地是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

我更喜欢将任务排队到像 exq(redis 支持(或 ecto_job(postgresql 支持(这样的作业系统中。

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

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

最新更新