If you did it in Erlang, as per the other question you referenced...
You save the timer reference and call erlang:cancel_timer/1 to stop it from firing (if it hasn't already). You have to watch out for this 'fired already' race condition, where the trigger message is already in your message queue when you cancel the timer. You might or might not care about this, but if it's important that you never carry out the action after the trigger has been cancelled then you need to create a reference (or you could use a counter) when you setup a timed message, and when you get a trigger you have to check that it relates to the latest one.
The code from the other question then becomes:
-define(INTERVAL, 60000). % One minute
init(Args) ->
...
% Start first timer
MyRef = erlang:make_ref(),
{ok, TRef} = erlang:send_after(?INTERVAL, self(), {trigger, MyRef}),
...
{ok, State#your_record{
timer = TRef,
latest = MyRef
}}.
% Trigger only when the reference in the trigger message is the same as in State
handle_info({trigger, MyRef}, State = #your_record{latest=MyRef}) ->
% Do the action
...
% Start next timer
MyRef = erlang:make_ref(),
{ok, TRef} = erlang:send_after(?INTERVAL, self(), trigger),
...
{ok, State#your_record{
timer = TRef,
latest = MyRef
}}.
% Ignore this trigger, it has been superceeded!
handle_info({trigger, _OldRef}, State) ->
{ok, State}.
And something like this to reset the timer:
handle_info(reset, State = #your_record{timer=TRef}) ->
% Cancel old timer
erlang:cancel_timer(TRef),
% Start next timer
MyNewRef = erlang:make_ref(),
{ok, NewTRef} = erlang:send_after(?INTERVAL, self(), trigger),
{ok, State#your_record{
timer = NewTRef,
latest = MyNewRef
}}.
A call might be more appropriate for the cancel function, but that depends on your app so it's up to you.
Technically, it's not necessary to cancel the timer, because once you've created a new state with your new reference, even if the old timer carries on, it'll be ignored when it fires, but I think it's best to tidy up really.
Process.send_after(self(), :work, 60_000)
does cannot be cancelled with:timer.cancel(timer)
as it returns{:error, :badarg}
. However, I can use:erlang.cancel_timer(timer)
. I am using Elixir v1.1.1. – Encincture