View Source Toolbox.Incident (toolbox v5.3.2)

Module extends Toolbox.Workflow and abstracts how regular incident behaves.

Wraps around Toolbox.Workflow and adds some additional callbacks to manage incident in asset map. This module works very much like regular workflow, but some additional properties can be specified. Contrary to a regular workflow, this automatically generates OAs to manage the incident in asset map and therefore syncs the general state of this workflow with the incident asset.

Start by creating a definition (see new/0, add_transition/2 and build/1) which describes the workflow of the incident. Then, you can create a new instance based on that definition with new_instance/7.

Summary

Functions

Link to this function

add_transition(wf, params)

View Source
@spec add_transition(Toolbox.Workflow.t(), Keyword.t()) :: Toolbox.Workflow.t()

Adds a new transition to incident workflow definition.

Incident workflow is a finite state machine. Transition defines how workflow changes its state from one to another and what must be done during the state change.

Incident transition is defined by params parameter. params is a keyword list where each transition parameter has its key. Parameters may be either required or optional. Some parameters have predefined keys. These parameters are used to control workflow. The developer of the scenario can add his own parameters to enrich function of the workflow with features that the standard workflow module does not provide. These parameters can have any key except predefined ones.

If add_transition/2 succeeds it returns a two level Toolbox.Workflow.Transition structure.

  • The first level contains parameters important for workflow control. Some parameters are copied from param and some are computed.
  • The second level is located under attributes key. It contains parameters important for workflow control and all parameters defined by scenario developer.

Transition structure is passed, alongside with instance status and message to all callback functions. The scenario developer can evaluate them inside the function.

  • from - the state of the workflow from which the transition starts.

    • required parameter
  • to - the state of the workflow after transition is completed.

    • required parameter
  • description_before - transition from from state to to state generates an output action. The output action contains simplified list of all possible states that can be reached from to state. The list is stored in body.attributes["future"]. Each entry of the list is a map. The description before is assigned to description key of that map. The description is intended to provide the human readable description of the conditions leading to the particular state.

    • required parameter
  • description_after - the aforementioned output action contains a list of all state changes that the workflow has already passed through. That list is stored in body.attributes["history']. Each entry of the list is a map containing details of the state. The description_after is copied to the "description" key of the map. The description is intended to provide human readable description about the past state change.

    • required parameter
  • severity - an integer from 1 to 4. The severity of the incident after transition to to state.

    • optional parameter
  • when - predicate used to select the transition which will be executed.

    • optional parameter
    • there can be multiple when definitions in list, all definitions are evaluated with && boolean operator
    • possible when definitions are:
      • {Module, function}, where function accepts transition, instance and message as args, returns boolean
      • {:timeout, timeout}, where timeout is defined in milliseconds (transition is then automatically executed when time elapses the specified value)
      • {:=, [path, to, state, key], value} (transition is executed if the specified field of state reaches the specified value)
  • then - callback used to update workflow instance state during transition execution.

    • optional parameter
    • there can be multiple then definitions in list, all definitions are executed in given order
    • possible then definitions:
      • {Module, function}, where function accepts transition, instance and message as args, and returns {:ok, state()} to update the instance state
  • side_effects - callback used to generate side effects during transition execution.

    • optional parameter
    • there can be multiple side effect definitions in list, all definitions are executed in given order.
    • possible definitions:
      • {Module, function}, where function accepts transition, instance and message as args, and returns {:ok, [OA | Msg | OtherSideEffect]}
  • update_history_entry - callback used to modify transition execution history entry stored in asset map.

    • optional parameter
    • there can be multiple definitions in list, all definitions are executed in given order
    • this is usually used to interpolate description texts, or to add additional attributes to history
    • You can use this callback to set additional event parameters - event_* available in Runbox.Scenario.OutputAction.IncidentHistory (the keys are strings in this case).
    • possible definitions:
      • {Module, function}, where function accepts history entry, transition, instance and message as args and returns {:ok, history_entry}
  • update_possible_transition - callback used to modify possible future transitions stored in asset map.

    • optional parameter
    • there can be multiple definitions in list, all definitions are executed in given order
    • the callback is executed for each possible future transition
    • note this only modifies the items of future attribute of the incident asset, this has no effect on definition transitions
    • possible definitions:
      • {Module, function}, where function accepts possible transition, transition, instance and message as args, and returns {:ok, future_transition}
  • user_actions - specifies all possible user actions from the target state

    • a map of user actions that should be enabled once the transition is executed and incident is in the target state.
    • optional parameter
    • user actions are automatically deleted if not present in the next transition
    • keys are strings
    • values are {module, function}, this specifies the function to be called to generate the user action token (since tokens are not known in advance, they are generated by the specified function)
      • the function takes transition, instance, message as arguments and is expected to return {:ok, binary_token} to register the user action token
  • upsert_attributes - specifies additional attributes to be added to the incident asset.

    • optional parameter
    • list of callbacks to compute the additional attributes
    • each callback produces a map of additional attributes and this is merged into a single map where the latter has priority over the former
    • attributes cannot override attributes handled by this workflow incl. user actions, only other attributes can be added
    • possible definitions:
      • {Module, function}, where function accepts transition, instance and message as args, and should return {:ok, attribute_map}

    Any other keys of the params parameter are put into the map under attributes key of the Transition structure. They can be used inside callback functions for any purpose. For example for debugging:

    Code snippets

    def definition do
      Incident.new()
      |> Incident.add_transition(
        from: "detected",
        to: "rare",
        when: [{__MODULE__, :rare_message_arrived?}],
        description_before: "Other messages will arrive",
        description_after: "Rare message arrived",
        update_history_entry: [{__MODULE__, :update_history_entry}],
        my_debug_key: "This should be a very rare transition"
        )
        ...
      |> Incident.build()
    end
    
    def update_history_entry(history, transition, _workflow_instance, message) do
      Logger.info(transition.attributes.my_debug_key)
      ...
      {:ok, new_history}
    end

When a message is evaluated the callbacks above are run in the following order.

  1. when callbacks are evaluated to see if the current transition is ready to be executed. If not the next transition is tried.
  2. then callbacks are evaluated to update the instance state.
  3. user_actions is evaluated, all callbacks specified inside are executed and all user action tokens are calculated.
  4. update_history_entry callbacks are evaluated to update the new history entry
  5. update_possible_transition callbacks are evaluated to update the new possible future transitions
  6. upsert_attributes callbacks are evaluated to gather additional attributes
  7. side_effects callbacks are evaluated to acquire the list of all additional output actions

All text bearing attributes (such as subject, description_before, description_after) have access to incident metadata dictionary. This dictionary contains these, keys:

  • type - incident type
  • id - incident id
  • transition - transition attributes dictionary containing from, to, severity keys
  • state - dictionary containing user defined state
  • message - altworx message which triggered given transition

Metadata can be accessed via interpolation defined as {{}}, e.g. {{state.foo.bar}}, {{message.body.foo}}. There is also an option to reference assets in those attributes, see Runbox.Scenario.OutputAction.interpolable/0.

Link to this function

append_create_incident_output_actions(tran, inc_inst, msg)

View Source
Link to this function

append_update_incident_output_actions(tran, inc_inst, msg)

View Source
@spec build(Toolbox.Workflow.t()) ::
  {:ok, Toolbox.Workflow.t()}
  | {:error, :transition_from_required}
  | {:error, :transition_to_required}
  | {:error, :description_after_required}
  | {:error, :description_before_required}
  | {:error, {:bad_callback, {atom(), atom()}}}
  | {:error, :multiple_init_statuses}
  | {:error,
     {:user_actions_invalid | :upsert_attributes_invalid, reason :: String.t()}}
Link to this function

handle_message(wf, inc_inst, msg)

View Source
@spec handle_message(
  Toolbox.Workflow.t(),
  Toolbox.Workflow.Instance.t(),
  Toolbox.Message.t()
) ::
  {:ok, [Runbox.Scenario.OutputAction.oa_params()],
   Toolbox.Workflow.Instance.t()}
  | {:terminated, [Runbox.Scenario.OutputAction.oa_params()],
     Toolbox.Workflow.Instance.t()}
  | {:error, :not_built_yet}
  | {:error, :status_mismatch}

Uses given incident workflow definition and message to update state of given instance.

If no configured workflow transition matches, nothing will happen = instance state will remain the same.

Order of callback execution:

  1. when definitions of transitions in definition order
  2. then definitions of matching transition
  3. update history entry definitions of matching transition
  4. update possible transition definitions of matching transition
  5. side effects definitions of matching transition
@spec new() :: Toolbox.Workflow.t()

Creates new blank incident workflow definition

Link to this function

new_instance(wf, status, type, id, state, msg, params)

View Source
@spec new_instance(
  Toolbox.Workflow.t(),
  Toolbox.Workflow.status(),
  String.t(),
  String.t(),
  map(),
  Toolbox.Message.t(),
  Keyword.t()
) ::
  {:ok, [Runbox.Scenario.OutputAction.oa_params()],
   Toolbox.Workflow.Instance.t()}
  | {:terminated, [Runbox.Scenario.OutputAction.oa_params()],
     Toolbox.Workflow.Instance.t()}
  | {:error, :unknown_status}
  | {:error,
     {:user_actions_invalid | :upsert_attributes_invalid, reason :: String.t()}}

Creates new incident instance for given workflow.

params can be used to specify additional transition-like parameters. actors parameter is evaluated only when new_instance/7 is called and is not stored in the instance. It is a listing of actors used when an incident is created. Its format is a list of maps where id and type are mandatory keys. id and type references an asset. For other available options see add_transition/2.

Link to this function

update_incident_history_entry(history_entry, tran, inc_inst, msg)

View Source
@spec update_incident_history_entry(
  map(),
  Toolbox.Workflow.Transition.t(),
  Toolbox.Workflow.Instance.t(),
  Toolbox.Message.t()
) :: {:ok, map()}
Link to this function

update_incident_possible_transition(pos_tran, tran, inc_inst, msg)

View Source
@spec update_incident_possible_transition(
  map(),
  Toolbox.Workflow.Transition.t(),
  Toolbox.Workflow.Instance.t(),
  Toolbox.Message.t()
) :: {:ok, map()}
Link to this function

update_incident_state(arg1, inc_inst, arg3)

View Source
@spec update_incident_state(
  Toolbox.Workflow.Transition.t(),
  Toolbox.Workflow.Instance.t(),
  Toolbox.Message.t()
) :: {:ok, map()}
Link to this function

update_user_actions(transition, instance, msg)

View Source
@spec update_user_actions(
  Toolbox.Workflow.Transition.t(),
  Toolbox.Workflow.Instance.t(),
  Toolbox.Message.t()
) :: {:ok, map()}
Link to this function

validate_upsert_attributes(upsert_attributes_def)

View Source