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 thia.md...@gmail.com <
thia.mdossan...@gmail.com> 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,
> woj...@wojtekmach.pl escreveu:
>
>> Check out Task.yield_many/2 (
>> https://hexdocs.pm/elixir/Task.html#yield_many/2) :-)
>>
>> On 31 Mar 2021, at 22:54, thia.md...@gmail.com <thia.md...@gmail.com>
>> 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 elixir-lang-co...@googlegroups.com.
>> 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 elixir-lang-core+unsubscr...@googlegroups.com.
> 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 elixir-lang-core+unsubscr...@googlegroups.com.
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.

Reply via email to