lib/runbox/runtime/runtime_instruction.ex

defmodule Runbox.Runtime.RuntimeInstruction do
  @moduledoc group: :output_actions
  @moduledoc """
  Struct produced by scenario representing instruction for runtime.
  """

  alias __MODULE__, as: RuntimeInstruction

  defstruct body: nil

  defmodule Timeout do
    @moduledoc group: :output_actions
    @moduledoc """
    Instruction to register unit timeout.

    Use `Runbox.Runtime.RuntimeInstruction.register_timeout/1` to create this runtime instruction.
    """

    alias Runbox.Message, as: Msg

    defstruct timeout_message: nil

    @typedoc "Struct representing unit timeout registration."
    @type t :: %Timeout{timeout_message: %Msg{}}
  end

  @typedoc "Struct produced by scenario representing instruction for runtime."
  @type t :: %RuntimeInstruction{body: Timeout.t()}

  @doc """
  Creates an runtime instruction to register a given timeout message.

  Timeouts allow scenarios to be notified at a specified time. This is useful when you want to
  perform something for example in 10 minutes from now or at tomorrow's noon (both in terms
  of the external time).

  When registering a timeout, you have to provide a message. This message will arrive to your
  run exactly at the time specified inside its `timestamp` field. Which component of your run
  will handle the message depends on the type of runtime that your scenario is based on.
  See docs of the particular runtime type for more details.

  Usually, you can use the return value of `register_timeout/1` wherever an output action is
  expected.

  ## Example

      register_timeout(%Runbox.Message{
        timestamp: now + :timer.minutes(10),
        type: :check_if_asset_has_been_repaired_and_send_a_notification_if_not,
        body: %{
          broken_asset: %{type: "/assets/router", id: "192.168.100.115"}
        }
      })
  """
  def register_timeout(timeout_message) do
    %RuntimeInstruction{body: %Timeout{timeout_message: timeout_message}}
  end
end