ex-aws / ex_aws

A flexible, easy to use set of clients AWS APIs for Elixir
https://hex.pm/packages/ex_aws
MIT License
1.26k stars 521 forks source link

partial step function binding example #937

Open kacorvus opened 1 year ago

kacorvus commented 1 year ago

My coworker implemented this, it may be useful to someone else:

defmodule ExAws.StepfunctionRuntime do
  @moduledoc """
  Provides AWS Step Function (State Machine) features such as success and failure callbacks, etc.
  """

  @doc """
  Responds with success to the step function state machine callback, passing data along the way.
  Usage:
    case ExAws.StepfunctionRuntime.send_task_success(data) do
      {:error, {:http_error, status, %{body: body}}} ->
        :error
      {:ok, %{}} ->
        :ok
    end
  """
  @spec send_task_success(%{taskToken: String.t(), output: String.t()}) :: {:ok, term} | {:error, term}
  def send_task_success(%{taskToken: _token, output: _output} = data) do
    data
    |> get_send_task_success_operation()
    |> ExAws.request()
  end

  @doc """
  Responds with failure to the step function state machine callback, passing data along the way.
  Usage:
    case ExAws.StepfunctionRuntime.send_task_failure(data) do
      {:error, {:http_error, status, %{body: body}}} ->
        :error
      {:ok, %{}} ->
        :ok
    end
  """
  @spec send_task_failure(%{taskToken: String.t(), output: String.t()}) :: {:ok, term} | {:error, term}
  def send_task_failure(%{taskToken: _token, output: _output} = data) do
    data
    |> get_send_task_failure_operation()
    |> ExAws.request()
  end

  @doc """
  Reports to the step function state machine that the external process is still active.
  Usage:
    case ExAws.StepfunctionRuntime.send_task_heartbeat(data) do
      {:error, {:http_error, status, %{body: body}}} ->
        :error
      {:ok, %{}} ->
        :ok
    end
  """
  @spec send_task_heartbeat(%{taskToken: String.t()}) :: {:ok, term} | {:error, term}
  def send_task_heartbeat(%{taskToken: _token} = data) do
    data
    |> get_send_heartbeat_operation()
    |> ExAws.request()
  end

  defp get_send_task_success_operation(data), do: get_step_function_operation("AWSStepFunctions.SendTaskSuccess", data)
  defp get_send_task_failure_operation(data), do: get_step_function_operation("AWSStepFunctions.SendTaskFailure", data)
  defp get_send_heartbeat_operation(data), do: get_step_function_operation("AWSStepFunctions.SendTaskHeartbeat", data)

  defp get_step_function_operation(target, data) do
    %ExAws.Operation.JSON{
      http_method: :post,
      headers: [
        {"x-amz-target", target},
        {"content-type", "application/x-amz-json-1.0"}
      ],
      path: "/",
      data: data,
      service: :states
    }
  end
end