+1 for yield_first(tasks, n, timeout)

On Thu, Apr 1, 2021, 01:11 José Valim <[email protected]> wrote:

> It was not possible to implement yield_first in Elixir but now that we
> have map_get in guards, we can easily do so by putting all refs in a map
> and only getting messages from the inbox where the ref is in the map. The
> number of tasks to wait and the maximum timeout should be configurable too.
> For example:
>
>     yield_first(task, 3, 1000)
>
> The above will yield the first 3 tasks within 1000ms. It should have the
> same result type as yield_many. In this sense, yield_many becomes a special
> case of yield_first where you want to yield on all given tasks.
>
> Another option is to not introduce a new function but instead introduce a
> new argument to yield_many with the limit to yield:
>
>     yield_many(task, 1000, 3)
>
>
>
> On Wed, Mar 31, 2021 at 11:52 PM [email protected] <
> [email protected]> wrote:
>
>> I think the proposal would work differently from yield_many. yield_many
>> "receives a list of tasks and waits for their replies in the given time
>> interval".
>> The proposal of the new function is to return as soon as the first task
>> finishes.
>>
>> For example, if we start tasks to make call to 3 different remote APIs,
>> with different response times.
>>
>> API A - 50ms
>> API B - 500ms
>> API C - 1500ms
>>
>> tasks = [
>>   Task.async(&api_a/0),
>>   Task.async(&api_b/0),
>>   Task.async(&api_c/0)
>> ]
>>
>> # returns result of API A and API B waiting for 1000ms
>> Task.yield_many(tasks, 1000)
>>
>> With run using `yield_many` we would wait for the 1000ms and get the
>> responses of API A and API B.
>>
>> The proposal of the new function is to return as soon as we get a
>> response.
>> Using the same example of the 3 calls, we would wait only for 50ms (as
>> soon as the first task finishes) and return the result of the first task
>> finishing, without waiting for the other call.
>>
>> tasks = [
>>   Task.async(&api_a/0),
>>   Task.async(&api_b/0),
>>   Task.async(&api_c/0)
>> ]
>>
>> # returns only result of API A waiting for 50ms
>> Task.proposed_function(tasks)
>>
>> Em quarta-feira, 31 de março de 2021 às 18:06:47 UTC-3,
>> [email protected] escreveu:
>>
>>> Check out Task.yield_many/2 (
>>> https://hexdocs.pm/elixir/Task.html#yield_many/2) :-)
>>>
>>> On 31 Mar 2021, at 22:54, [email protected] <[email protected]>
>>> wrote:
>>>
>>> *Proposal*
>>>
>>> Add a function to the Task module that takes a list of tasks, and
>>> returns as soon as one of the tasks finishes, shuting down the other tasks.
>>> The behaviour would pretty similar to what Javascript have with
>>> Promise.any
>>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any
>>>
>>> *Motivation*
>>>
>>> One scenario that it could be useful is when we are integrating with
>>> multiple APIs (providers) of the same data, and we want only the fastest
>>> result without needing to wait for the other requests to complete.
>>>
>>> Today I think this could be implemented with something similar to the
>>> following code:
>>>
>>> tasks = [
>>>   Task.async(&heavy_fun_1/0),
>>>   Task.async(&heavy_fun_2/0),
>>>   Task.async(&heavy_fun_3/0)
>>> ]
>>>
>>> receive do
>>>   {ref, result} ->
>>>     tasks
>>>     |> Enum.reject(fn task -> task.ref == ref end)
>>>     |> Enum.each(&Task.shutdown/1)
>>>
>>>     result
>>> after
>>>   5000 ->
>>>     {:error, :timeout}
>>> end
>>>
>>> However that seems to be a common enough pattern to add to the standard
>>> library.
>>>
>>> *Questions*
>>>
>>> - Am I missing something here and this could already be easily
>>> accomplished with the existing API?
>>> - What should be the behaviour when the first task to complete exits?
>>>
>>> --
>>> 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/59a5b5af-528b-4f1f-8e17-6dad9edfe9ccn%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/59a5b5af-528b-4f1f-8e17-6dad9edfe9ccn%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>>
>>> --
>> 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/fe8d048f-605b-4b7a-ad2d-64fb11727d4dn%40googlegroups.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/fe8d048f-605b-4b7a-ad2d-64fb11727d4dn%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
> --
> 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/CAGnRm4L%2BogpwDohNaRoZHkT0%3DkOdFROdT37BQJx3k%3D%3DzZqQzAA%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4L%2BogpwDohNaRoZHkT0%3DkOdFROdT37BQJx3k%3D%3DzZqQzAA%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CAKC64%2BwFh20dRTVnJi5QC8Ekk5CNcSx8k8jW_xBP65rOYGukYw%40mail.gmail.com.

Reply via email to