defmodule Edeliver.Relup.Instructions.Sleep do
@moduledoc """
This upgrade instruction is intended for testing only
and just sleeps the given amount of seconds. This can
be used to test instructions which suspend processes
at the beginning of the upgrade before the new code is
installed. Usage:
```
Edeliver.Relup.Instructions.Sleep.modify_relup(config, _seconds = 30)
```
It prints a countown in the upgrade script which was
started by the `$APP/bin/$APP upgrade $RELEASE` command.
"""
use Edeliver.Relup.RunnableInstruction
@spec modify_relup(instructions::Instructions.t, config::Edeliver.Relup.Config.t, seconds::integer) :: Instructions.t
def modify_relup(instructions = %Instructions{}, _config = %{}, seconds \\ 30) do
call_this_instruction = call_this(max(0, seconds))
insert_where_fun = insert_where()
instructions |> insert_where_fun.(call_this_instruction)
|> ensure_module_loaded_before_instruction(call_this_instruction, __MODULE__)
end
@doc """
Appends this instruction to the instructions after the "point of no return"
but before any instruction which loads or unloads new code,
(re-)starts or stops any running processes, or (re-)starts
or stops any application or the emulator.
"""
def insert_where, do: &append_after_point_of_no_return/2
@doc """
Waits the given amount of seconds and prints a countdown
in the upgrade script which was started by the
`$APP/bin/$APP upgrade $RELEASE` command.
"""
@spec run(seconds::integer) :: :ok
def run(seconds) do
Logger.info "Waiting #{inspect seconds} seconds..."
wait(seconds, seconds)
Logger.info "Waited #{inspect seconds} seconds."
end
defp wait(_remaining_seconds = 0, seconds) do
format_in_upgrade_script '\r---> Waited ~b seconds. ~n', [seconds]
end
defp wait(remaining_seconds, seconds) do
format_in_upgrade_script '\r---> Waiting ~b seconds... ', [remaining_seconds]
receive do
after 1000 -> wait(remaining_seconds - 1, seconds)
end
end
end