Packages
altworx_runbox
7.0.0
25.0.0
24.0.0
23.1.0
23.0.0
22.2.0
22.1.0
22.0.0
21.2.0
21.1.2
21.1.1
21.1.0
21.0.0
20.0.0
19.0.0
18.0.0
17.2.0
17.1.0
17.0.1
17.0.0
16.2.0
16.1.0
16.0.0
15.0.0
14.1.0
14.0.1
14.0.0
13.0.3
13.0.2
13.0.1
13.0.0
12.1.0
12.0.0
11.0.1
11.0.0
10.0.0
9.0.0
8.0.0
7.0.1
7.0.0
6.0.0
5.0.0
4.0.0
3.0.0
2.1.0
2.0.0
1.4.1
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.1.3
0.1.2
0.1.1
0.1.0
Runbox is a library for running Altworx scenarios.
Current section
Files
Jump to
Current section
Files
lib/runbox/runtime/output_action.ex
defmodule Runbox.Runtime.OutputAction do
@moduledoc """
Output Action for internal use by Runtime
"""
alias Runbox.Runtime.OABody
alias Runbox.Scenario.OutputAction, as: ScenarioOA
alias __MODULE__, as: OA
defstruct [:body, :timestamp, :scenario_id, :run_id]
@typedoc "Runtime Output Action"
@type t :: %__MODULE__{
body: ScenarioOA.oa_params() | ScenarioOA.BadOutputAction.t(),
timestamp: integer(),
scenario_id: String.t(),
run_id: String.t()
}
@doc """
Creates a new output action.
To produce a valid output action, the `params` have to be one of the accepted
structs. See the documentation of the particular structs for details.
If the `params` are not one of the accepted structs or some of the fields do
not pass validation, it returns an output action with body set to
`t:Runbox.Scenario.OutputAction.BadOutputAction.t/0` with original params
inside.
"""
@spec new(params :: ScenarioOA.oa_params(), integer(), String.t(), String.t()) :: t()
def new(params, timestamp, scenario_id, run_id) do
if is_oa_body?(params) and valid_body?(params) do
%OA{body: params, timestamp: timestamp, scenario_id: scenario_id, run_id: run_id}
else
body = %ScenarioOA.BadOutputAction{params: params}
%OA{body: body, timestamp: timestamp, scenario_id: scenario_id, run_id: run_id}
end
end
@doc """
Returns `true` if valid output action.
"""
@spec valid?(OA.t() | any()) :: boolean()
def valid?(%OA{body: body, timestamp: ts, scenario_id: sid, run_id: rid}) do
is_oa_body?(body) and valid_body?(body) and is_integer(ts) and is_binary(sid) and is_binary(rid)
end
def valid?(_) do
false
end
@doc """
Returns `true` if valid output action body.
"""
@spec is_oa_body?(ScenarioOA.oa_params() | any()) :: boolean()
def is_oa_body?(params) do
not is_nil(OABody.impl_for(params))
end
defp valid_body?(params) do
OABody.valid?(params)
end
end
defprotocol Runbox.Runtime.OABody do
@moduledoc false
@spec valid?(t) :: boolean()
def valid?(body)
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.UpsertAssetAttributes do
def valid?(%Runbox.Scenario.OutputAction.UpsertAssetAttributes{
type: type,
id: id,
attributes: attributes
}) do
is_binary(type) and
id_valid?(id) and
is_map(attributes)
end
defp id_valid?(id), do: is_binary(id) and not String.contains?(id, "/")
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.DeleteAssetAttributes do
def valid?(%Runbox.Scenario.OutputAction.DeleteAssetAttributes{
type: type,
id: id,
attributes: attributes
}) do
is_binary(type) and
is_binary(id) and
is_map(attributes)
end
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.DeleteAllAssetAttributes do
def valid?(%Runbox.Scenario.OutputAction.DeleteAllAssetAttributes{
type: type,
id: id
}) do
is_binary(type) and is_binary(id)
end
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.UpsertEdge do
def valid?(%Runbox.Scenario.OutputAction.UpsertEdge{
from_type: from_type,
from_id: from_id,
to_type: to_type,
to_id: to_id,
type: type
}) do
is_binary(from_type) and is_binary(from_id) and
is_binary(to_type) and is_binary(to_id) and
is_binary(type)
end
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.DeleteEdge do
def valid?(%Runbox.Scenario.OutputAction.DeleteEdge{
from_type: from_type,
from_id: from_id,
to_type: to_type,
to_id: to_id,
type: type
}) do
is_binary(from_type) and is_binary(from_id) and
is_binary(to_type) and is_binary(to_id) and
is_binary(type)
end
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.Notification do
alias Runbox.Scenario.OutputAction.Notification
def valid?(%Notification{
type: type,
primary_asset: primary_asset,
ids: ids,
aqls: aqls,
priority: priority,
metadata: metadata,
direct_subscriptions: direct_subscriptions,
attachments: attachments
}) do
type_valid?(type) and
ids_valid?(ids) and
is_map(aqls) and
is_map(metadata) and
priority_valid?(priority) and
direct_subscriptions_valid?(direct_subscriptions) and
primary_asset_valid?(primary_asset) and
attachments_valid?(attachments)
end
defp type_valid?(type), do: is_binary(type) or (is_atom(type) and not is_nil(type))
defp priority_valid?(priority), do: priority in [:low, :medium, :high, "low", "medium", "high"]
defp ids_valid?(ids), do: is_list(ids) and Enum.all?(ids, &is_binary/1)
defp direct_subscriptions_valid?(ds), do: is_nil(ds) or is_list(ds)
defp primary_asset_valid?(pa), do: is_nil(pa) or is_binary(pa)
defp attachments_valid?(at), do: is_nil(at) or is_list(at)
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.Event do
alias Runbox.Scenario.OutputAction.Event
def valid?(%Event{
type: type,
template: template,
actors: actors,
params: params,
origin_messages: origin_messages
}) do
valid_type?(type) and
is_binary(template) and
is_map(actors) and
is_map(params) and
is_list(origin_messages)
end
defp valid_type?(type), do: is_binary(type) or (is_atom(type) and not is_nil(type))
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.ExecuteSQL do
alias Runbox.Scenario.OutputAction.ExecuteSQL
def valid?(%ExecuteSQL{
db_connection: db_connection,
sql_query: sql_query,
data: data,
type: type
}) do
is_map(db_connection) and
is_binary(sql_query) and
is_list(data) and
type in [:postgresql, "postgresql"]
end
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.Incident do
alias Runbox.Scenario.OutputAction.Incident
alias Runbox.Scenario.OutputAction.IncidentActor
alias Runbox.Scenario.OutputAction.IncidentFuture
alias Runbox.Scenario.OutputAction.IncidentHistory
def valid?(%Incident{
id: id,
future: future,
history: history,
actors: actors
}) do
id_valid?(id) and
future_valid?(future) and
history_valid?(history) and
actors_valid?(actors)
end
defp id_valid?(id), do: is_binary(id) and not String.contains?(id, "/")
defp future_valid?(future),
do: is_list(future) and Enum.all?(future, &match?(%IncidentFuture{}, &1))
defp history_valid?(history),
do: is_list(history) and Enum.all?(history, &match?(%IncidentHistory{}, &1))
defp actors_valid?(nil), do: true
defp actors_valid?(actors),
do: is_list(actors) and Enum.all?(actors, &match?(%IncidentActor{}, &1))
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.IncidentPatch do
alias Runbox.Scenario.OutputAction.IncidentPatch
alias Runbox.Scenario.OutputAction.IncidentActor
alias Runbox.Scenario.OutputAction.IncidentFuture
alias Runbox.Scenario.OutputAction.IncidentHistory
def valid?(%IncidentPatch{
future: future,
history: history,
actors: actors
}) do
future_valid?(future) and
history_valid?(history) and
actors_valid?(actors[:add]) and
actors_valid?(actors[:remove])
end
defp future_valid?(nil), do: true
defp future_valid?(future),
do: is_list(future) and Enum.all?(future, &match?(%IncidentFuture{}, &1))
defp history_valid?(nil), do: true
defp history_valid?(history),
do: is_list(history) and Enum.all?(history, &match?(%IncidentHistory{}, &1))
defp actors_valid?(nil), do: true
defp actors_valid?(actors),
do: is_list(actors) and Enum.all?(actors, &match?(%IncidentActor{}, &1))
end
defimpl Runbox.Runtime.OABody, for: Runbox.Scenario.OutputAction.BadOutputAction do
def valid?(_), do: true
end