Skip to content

Commit

Permalink
Add a timeout for the hydrating function
Browse files Browse the repository at this point in the history
  • Loading branch information
bchamagne committed Mar 22, 2023
1 parent 7d11f48 commit 9017cec
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
15 changes: 14 additions & 1 deletion lib/archethic/oracle_chain/services/hydrating_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ defmodule Archethic.OracleChain.Services.HydratingCache do
:refresh_interval,
:value,
:hydrating_task,
:hydrating_timer
:hydrating_timer,
:hydrating_function_timeout
])
end

Expand All @@ -44,6 +45,7 @@ defmodule Archethic.OracleChain.Services.HydratingCache do
refresh_interval = Keyword.fetch!(options, :refresh_interval)
mfa = Keyword.fetch!(options, :mfa)
ttl = Keyword.get(options, :ttl, :infinity)
hydrating_function_timeout = Keyword.get(options, :hydrating_function_timeout, 5000)

# start hydrating as soon as init is done
hydrating_timer = Process.send_after(self(), :hydrate, 0)
Expand All @@ -53,6 +55,7 @@ defmodule Archethic.OracleChain.Services.HydratingCache do
%State{
mfa: mfa,
ttl: ttl,
hydrating_function_timeout: hydrating_function_timeout,
refresh_interval: refresh_interval,
hydrating_timer: hydrating_timer
}}
Expand All @@ -69,6 +72,7 @@ defmodule Archethic.OracleChain.Services.HydratingCache do
def handle_info(
:hydrate,
state = %State{
hydrating_function_timeout: hydrating_function_timeout,
mfa: {m, f, a}
}
) do
Expand All @@ -82,9 +86,18 @@ defmodule Archethic.OracleChain.Services.HydratingCache do
end
end)

# we make sure that our hydrating function does not hang
Process.send_after(self(), {:kill_hydrating_task, hydrating_task}, hydrating_function_timeout)

{:noreply, %State{state | hydrating_task: hydrating_task}}
end

def handle_info({:kill_hydrating_task, task}, state) do
Task.shutdown(task, :brutal_kill)

{:noreply, state}
end

def handle_info(
{ref, result},
state = %State{
Expand Down
19 changes: 19 additions & 0 deletions test/archethic/oracle_chain/services/hydrating_cache_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,23 @@ defmodule ArchethicCache.OracleChain.Services.HydratingCacheTest do

assert :error = HydratingCache.get(pid, 1)
end

test "should kill the task if hydrating function takes longer than timeout" do
{:ok, pid} =
HydratingCache.start_link(
mfa: {Process, :sleep, [100]},
refresh_interval: 100,
hydrating_function_timeout: 10,
ttl: :infinity
)

:erlang.trace(pid, true, [:receive])
assert_receive {:trace, ^pid, :receive, :hydrate}
assert_receive {:trace, ^pid, :receive, {:kill_hydrating_task, _}}

refute Process.alive?(:sys.get_state(pid).hydrating_task.pid)
assert Process.alive?(pid)

assert :error = HydratingCache.get(pid)
end
end

0 comments on commit 9017cec

Please sign in to comment.