在x个时间后重试失败功能

时间:2018-01-21 00:57:40

标签: elixir phoenix-framework

问题:

我有一个被VIA Cronjob触发的功能。这个cronjob在晚上10点触发该功能,但是假设该功能没有正确处理所需的数据。我想失败,但然后让功能重试1小时。我该如何处理这个问题?

CODE:

  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实现这一目标?谢谢你的帮助!

3 个答案:

答案 0 :(得分:2)

您可以使用genserver在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

答案 1 :(得分:2)

使用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

答案 2 :(得分:1)

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

从那里它将自动重试一些最大值,并在重试之间延迟。

它还具有服务器重启等幸存的好处。