Current section
Files
Jump to
Current section
Files
lib/states_language/ast/wait.ex
defmodule StatesLanguage.AST.Wait do
@moduledoc false
@behaviour StatesLanguage.AST
alias StatesLanguage.AST.Resource
alias StatesLanguage.Node
@impl true
# credo:disable-for-lines:7
def create(%Resource{
name: state_name,
node:
%Node{
next: next_state,
is_end: is_end
} = node
}) do
duration = get_wait_duration_milliseconds(node)
quote location: :keep do
import StatesLanguage.AST.Wait,
only: [get_timestamp_diff: 1]
@impl true
def handle_event(
:internal,
:handle_resource,
unquote(state_name) = state,
%StatesLanguage{data: data} = sl
) do
Logger.debug("Handling Wait resource for #{state}")
# credo:disable-for-lines:22
dur =
case AST.wait_duration(unquote(duration)) do
{:path, path} ->
Logger.debug("getting wait time from path #{path}")
val = run_json_path(path, data)
case val do
%DateTime{} = future ->
get_timestamp_diff(future)
seconds when is_number(seconds) ->
Logger.debug("Path value was seconds")
trunc(seconds * 1000)
datetime when is_binary(datetime) ->
Logger.debug("path value was timestamp")
{:ok, future, _off} = DateTime.from_iso8601(datetime)
get_timestamp_diff(future)
end
{:milli, milliseconds} ->
milliseconds
end
Logger.debug("Waiting #{dur}ms in state #{state}")
{:keep_state_and_data, [{:state_timeout, dur, dur}]}
end
@impl true
def handle_event(
:state_timeout,
duration,
unquote(state_name) = state,
%StatesLanguage{} = sl
) do
case AST.do_stop?(unquote(is_end)) do
true ->
:stop
false ->
actions = [{:next_event, :internal, :transition}]
Logger.debug(
"Moving from #{state} to #{unquote(next_state)} after waiting #{duration}ms"
)
{:keep_state_and_data, actions}
end
end
end
end
@spec get_timestamp_diff(DateTime.t()) :: integer()
def get_timestamp_diff(future) do
DateTime.diff(future, DateTime.utc_now(), :millisecond)
end
@spec get_wait_duration_milliseconds(Node.t()) ::
{:milli, integer()} | {:path, String.t()}
defp get_wait_duration_milliseconds(%Node{seconds: seconds}) when not is_nil(seconds),
do: {:milli, trunc(seconds * 1000)}
defp get_wait_duration_milliseconds(%Node{timestamp: future}) when not is_nil(future) do
{:milli, get_timestamp_diff(future)}
end
defp get_wait_duration_milliseconds(%Node{seconds_path: path}) when not is_nil(path),
do: {:path, path}
defp get_wait_duration_milliseconds(%Node{timestamp_path: path}) when not is_nil(path),
do: {:path, path}
end