It is quite a common scenario to run some bunch of work asynchronously inside the “main” computation. The most obvious example would be a web application user request. Elixir already comes with Task async/await facility for such case. However, it links the processes under the hood (links “caller” or “main” computation with asynchronous task). The downside of this approach is that if the task dies (e.g. raises an exception), the “main” computation will also die. In terms of web application user request it usually leads to generic
500 Internal Server Error (in most web server implementations). So it forces you either to apply some kind of “error handling strategy” (e.g. Plug.ErrorHandler) or to stick with “non-linking-facility” (e.g. Task.Supervisor.async_nolink/5). The former one could be an overkill for simple tasks (or can become a cumbersome solution for handling the errors from different parts of the application). The latter has even more serious flaw — if the “main” computation dies (e.g. connection was closed), the task will continue to run. Unless the task supervisor is linked to the “main” computation.
So I found myself reconstructing such facility for many web applications (spawn a local task supervisor and run tasks against it), when I need to apply a response time bounds (e.g. respond within a second or query an underlying service within 200ms). The library addresses this gap between Elixir’s kernel building blocks (asynchronous tasks and task supervisors) and synchronous total time limited expression evaluation.