I would prefer to not add another function and verb to the Task API. Otherwise it can be confusing to figure out which one you need from await, yield, shutdown and finish. The current API was designed to compose, so I would prefer to improve the documentation on both yield and shutdown to mention those scenarios.
On Tuesday, October 4, 2016, Myron Marston <[email protected]> wrote: > In our application, we commonly use tasks while responding to HTTP > requests to fetch metadata from the database that is used to “decorate” the > returned data with some non-essential bits of info (think things like tags, > added_at timestamps, etc). Given that this data is non-essential, we only > want to wait on the task for a limited amount of time, and if the database > query has not completed in that time, then we just want to respond without > the extra data. We’ve tended to use this pattern: > > task = Task.async(fn -> perform_db_query(...) end) > main_data = perform_main_request_logic(...) > case Task.yield(task, timeout) do > {:ok, result} -> merge_metadata(main_data, result) > nil -> > Task.shutdown(task) > main_dataend > > This has worked OK, but on a recent github issue > <https://github.com/elixir-lang/elixir/issues/5277#issuecomment-250872428>, > @fishcakez helped me realize there’s a race condition in this pattern. The > task could complete between the call to Task.yield/2 and Task.shutdown/1, > and the logic as I’ve written it would throw the result away. Instead, it > is better to do this at the end: > > case Task.yield(task, timeout) || Task.shutdown(task) do > {:ok, result} -> merge_metadata(main_data, result) > nil -> main_dataend > > Given that it’s an easy mistake to make, I think it would be beneficial if > Task.yield(task, > timeout) || Task.shutdown(task) was encapsulated as a function on the Task > module. Maybe something like Task.finish/2. Basically, it’s like > Task.await/2, but with a couple differences: > > If the task completes, it returns {:ok, result} instead of just result > If the task times out, it returns nil instead of causing an exit. > > If we weren’t concerned with backwards compatibility, it would make sense > to rename Task.await/2 to Task.await!/2 and then make this Task.await/2 — > but obviously we can’t do that. Task.finish/2 is the best name I’ve been > able to come up with. > > Thoughts? > > Myron > > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected] > <javascript:_e(%7B%7D,'cvml','elixir-lang-core%[email protected]');> > . > To view this discussion on the web visit https://groups.google.com/d/ > msgid/elixir-lang-core/146cc734-b511-44d7-b647- > 5a1bf0dd37f3%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/146cc734-b511-44d7-b647-5a1bf0dd37f3%40googlegroups.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- *José Valim* www.plataformatec.com.br Skype: jv.ptec Founder and Director of R&D -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JQnkJMgPRYpiwt35sRZOc-%3DL%3DW9kuOX_UW_TfWGUQ%2BmQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
