lib/toolbox/runtime/runtime_instruction.ex

defmodule Toolbox.Runtime.RuntimeInstruction do
  @moduledoc """
  Struct produced by scenario representing instruction for runtime.
  """

  alias __MODULE__, as: RuntimeInstruction

  defstruct body: nil

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

    alias Toolbox.Message, as: Msg

    defstruct unit_id: nil, timeout: nil, timeout_message: nil

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

  defmodule StartIncident do
    @moduledoc """
    Struct representing instruction to start incident process in server based runtime.
    """

    defstruct timestamp: nil,
              incident_id: nil,
              template: nil,
              attributes: nil,
              subscriptions: nil,
              actors: nil

    @typedoc "Struct representing instruction to start incident process in server based runtime."
    @type t :: %StartIncident{
            timestamp: integer,
            incident_id: String.t(),
            template: module,
            attributes: map,
            subscriptions: [{:unit, String.t()}],
            actors: [String.t()]
          }
  end

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

  @doc """
  Creates runtime instruction to register unit timeout from a message.
  """
  def register_timeout(timeout_message) do
    %RuntimeInstruction{
      body: %Timeout{timeout: timeout_message.timestamp, timeout_message: timeout_message}
    }
  end

  @doc """
  Creates runtime instruction to register unit timeout by giving the target time and message.

  Note that the `timeout` and `timeout_message.timestamp` should specify the same timestamp, unless
  unexpected things can happen.
  """
  def register_timeout(timeout, timeout_message) do
    %RuntimeInstruction{
      body: %Timeout{timeout: timeout, timeout_message: timeout_message}
    }
  end

  @doc """
  Creates runtime instruction to start incident process in server based runtime.
  """
  def start_incident(incident_id, timestamp, template, attributes, subscriptions, actors) do
    %RuntimeInstruction{
      body: %StartIncident{
        timestamp: timestamp,
        incident_id: incident_id,
        template: template,
        attributes: attributes,
        subscriptions: subscriptions,
        actors: actors
      }
    }
  end
end