I’m having some trouble understanding what the best approach is for dealing with slow GenServer calls. I’ve created an example of what I’m trying to do here: https://github.com/overture8/my_app.
Essentially, I have two GenServers: GenServer1
and GenServer2
. In GenServer1
I make a call to GenServer2.slow_thing()
, which is mocked to be a slow action - and given the 5 second default timeout of a GenServer call, I get a timeout error.
iex(1)> MyApp.GenServer1.do_somthing()
** (exit) exited in: GenServer.call(MyApp.GenServer1, :do_something, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:737: GenServer.call/3
iex(1)>
09:51:20.799 [error] GenServer MyApp.GenServer1 terminating
** (stop) exited in: GenServer.call(MyApp.GenServer2, :slow_thing, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:737: GenServer.call/3
(my_app) lib/my_app/gen_server1.ex:14: MyApp.GenServer1.handle_call/3
(stdlib) gen_server.erl:636: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:665: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.131.0>): :do_something
State: []
Client #PID<0.131.0> is alive
(kernel) code_server.erl:140: :code_server.call/1
(kernel) error_handler.erl:41: :error_handler.undefined_function/3
(iex) lib/iex/evaluator.ex:226: IEx.Evaluator.print_error/3
(iex) lib/iex/evaluator.ex:158: IEx.Evaluator.eval/4
(iex) lib/iex/evaluator.ex:61: IEx.Evaluator.loop/3
(iex) lib/iex/evaluator.ex:21: IEx.Evaluator.init/4
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
I can fix this by changing the default timeout in both GenServer1
and GenServer2
to something greater than 10 seconds (the sleep time mocked in GenServer2
). However, I’m not really sure what the best practice it here? I can’t use a cast because I want to have a return value.