Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MatchError in Task.Supervisor.async/1 in case of custom max_children option #7786

Closed
van-mronov opened this issue Jun 22, 2018 · 9 comments
Closed

Comments

@van-mronov
Copy link
Contributor

Environment

  • Elixir & Erlang/OTP versions (elixir --version):
    Erlang/OTP 21 [erts-10.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Elixir 1.7.0-dev (c3b0caa) (compiled with Erlang/OTP 21)

  • Operating system:
    macOS High Sierra

Current behavior

iex(1)> fun = fn -> receive do: (true -> true) end
#Function<20.127694169/0 in :erl_eval.expr/5>
iex(2)> {:ok, pid} = Task.Supervisor.start_link(max_children: 2)
{:ok, #PID<0.107.0>}
iex(3)> Task.Supervisor.async(pid, fun)
%Task{
  owner: #PID<0.104.0>,
  pid: #PID<0.109.0>,
  ref: #Reference<0.1607025971.2254700546.50905>
}
iex(4)> Task.Supervisor.async(pid, fun)
%Task{
  owner: #PID<0.104.0>,
  pid: #PID<0.111.0>,
  ref: #Reference<0.1607025971.2254700546.50934>
}
iex(5)> Task.Supervisor.async(pid, fun)
** (MatchError) no match of right hand side value: {:error, :max_children}
    (elixir) lib/task/supervisor.ex:376: Task.Supervisor.async/6

Expected behavior

Task.Supervisor.async/1 and other calls to start async task should return {:error, :max_children} if DynamicSupervisor cannot start child.

@josevalim
Copy link
Member

Good catch. Not sure about the behaviour here. We can't return {:error, :max_children} because we just return the task, so that would be confusing. So we may have to raise but something more meaningful.

@van-mronov
Copy link
Contributor Author

Yeah, I see. Also we have the same issue with async_stream calls. And, perhaps, raising error in spawn function makes sense.

@josevalim
Copy link
Member

async_stream allows us to return errors, so it is not a big problem there.

@van-mronov
Copy link
Contributor Author

So, what if add something like MaxChildrenError?

@josevalim
Copy link
Member

@van-mronov we generally do not add new exceptions for cases like this. But it may be worth if it can be raised on async and used as a signal on async_stream.

@michalmuskala
Copy link
Member

michalmuskala commented Jun 22, 2018

The interaction between a task supervisor with max_children and async_stream seems very fuzzy to me.

A possible desired behaviour there could be that if the child can't be started right away the stream will block until it can start (or the timeout fires). Returning :error tuple doesn't seem very useful, since it would need to return it for all the following elements most of the time - if it couldn't start one, it probably won't be able to start another one immediately after.

@van-mronov
Copy link
Contributor Author

Perhaps, it makes sense to use max_children (if it's specified) as default value for max_concurrency option of async_stream.

@josevalim
Copy link
Member

Perhaps, it makes sense to use max_children (if it's specified) as default value for max_concurrency option of async_stream.

If you are using max_concurrency, i would say there is no reason to set max_children. Maybe we should clarify this in the docs.

whatyouhide added a commit that referenced this issue Sep 29, 2018
Related to #7786.

Before this commit, when reaching the max children under a 
Task.Supervisor, we failed with a MatchError. Now, we're handling the 
"{:error, :max_children}" that we get from the DynamicSupervisor and 
raising a more meaningful error message. We're raising instead of 
returning an error tuple because async/2,4 are supposed to return the 
task directly.
whatyouhide added a commit that referenced this issue Sep 29, 2018
…8238)

Related to #7786.

Before this commit, when reaching the max children under a 
Task.Supervisor, we failed with a MatchError. Now, we're handling the 
"{:error, :max_children}" that we get from the DynamicSupervisor and 
raising a more meaningful error message. We're raising instead of 
returning an error tuple because async/2,4 are supposed to return the 
task directly.
@josevalim
Copy link
Member

Closing in favor of PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants