sezaru

sezaru

Case to use or not use :infinity as timeout for calls

Hello,

Setting the timeout value in my GenServer calls was always something that I found uncomfortable, it seemed to me that 5 seconds default was kinda a “random” number and I was not sure what number I needed to use.

At the same time, I was scared of using :infinity for it since you rarely see an example using it, so I thought it was not safe (I thought you would be stuck if the callee died or something like that).

Well, looking deeply I found this link Thoughts on when to use ‘infinity’ timeouts for gen_server:call and friends. They do discuss the call default timeout and says that it should be :infinity by default.

After that, I did some tests and indeed it seems to me to be very safe to use it as the default (and only use a timed timeout when it really makes sense). It fixed a lot of issues I had with timeouts when I changed the backend machine processing power which would often trigger these timeouts.

So, my question is a two-part one (sorry for that), the first part is, what is your opinion about that? Maybe Genserver documentation should be more clear about it (If it is I couldn’t find it sincerely)? Maybe we should have :infinity as the default timeout for calls as the link suggests?

The second part of the question is in regard of other timeouts configurations in the system that too are not really clear if they are safe to use :infinity or not.

For example, Ecto.Repo, you have the :timeout parameter for your config, this is what the documentation tells about it:

The time in milliseconds to wait for the query call to finish. :infinity will wait indefinitely (default: 15000)

As you can see, it mentions :infinity, but it is not clear (at least to me) if the query call is a Genserver.call or it is the call to the database server. If it is the first, I would consider safe to use :infinity since if the callee dies, we will not be stuck. But if it is referencing the database server, then my guess is that it could simply crash/disappear/whatever and it would never return from it, basically being locked in this call forever.

So, the second part of my question is, is it safe to use :infinity for the case of Ecto.Repo as an example? Do you know other libs that would not be?

Thank you very much.

Most Liked

lucaong

lucaong

The thing is, speaking about asynchronous calls in general and not referring to GenServer, it makes sense to explicitly timeout when something takes more than reasonable. With GenServer though, if the call times out, the caller fails, but the server is still running and trying to produce the result even after the timeout. In other words, the deadlock would still be there, as the GenServer would be still blocked. If one really wants to free up resources when an operation takes too long, a custom timeout logic on the GenServer side is better than a timeout on the caller.

Conversely, using a timeout of :infinity would at least ensure that if there is an unreasonable delay, it surfaces immediately. The right action to take is then to enforce a timeout logic that cleans up resources, which is not what the GenServer.call/3 timeout does.

The GenServer timeout was absolutely necessary back when gen_server could crash without the caller knowing about that. Nowadays it’s generally not the case anymore.

asummers

asummers

IMO :infinity an an antipattern. It could be easily replaced with 3 hours and have the same effect. Should this run for 3h? Probably not. So why say it can run for infinity? If I have an Ecto query that has to e.g. take a whole table lock, and it can’t get the lock (say for TRUNCATE), giving it an infinity timeout will cause it to hold a DB worker forever. Get enough of these and you have major resource contention on your DB.

asummers

asummers

If I have a single GenServer there’s only one message queue, so it exhibits the same resource contention as a DB. You can model this differently, of course, but naively using :infinity everywhere has the potential to deadlock your whole app. There are cases where you do need :infinity but I can’t think of any off the top of my head where saying 3 weeks or some equally silly large number would be less appropriate.

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement