PRs to improve the docs is always welcome! On Fri, Apr 2, 2021 at 21:02 thia.md...@gmail.com <thia.mdossan...@gmail.com> wrote:
> > And this made me wonder: is there any reason why you can't use > Task.async_stream? > > After testing, I'm sure we can accomplish the same thing that was proposed > with Task.async_stream. There is really no reason for an extra function. > > One thing that would be nice is to have an example for this usage in the > documentation. I honestly never thought in using Task.async_stream in this > way. > > WDYT? PRs for adding this example to the documentation would be welcome? > > Em sexta-feira, 2 de abril de 2021 às 08:39:18 UTC-3, emt...@gmail.com > escreveu: > >> Funny that exactly on this day that the proposal was opened I said in two >> groups the lack that I was doing something similar to "Promise.any" in >> Elixir. >> >> I needed it and found it complicated to do now, I had a job because I'm >> starting in Elixir. >> >> I would love to have another solution for what I did, when researching >> several APIs to return the CEP query to me and get the first valid result. >> >> I'm starting in Elixir and in love, and I made my first package with >> exactly this need: >> https://github.com/ciareis/cep-promise-elixir/blob/master/lib/cep_promise.ex#L52 >> >> I could probably write everything in a better way, but I still get there. >> >> Please implement something to facilitate this;) >> >> Elixir S2! >> Em sexta-feira, 2 de abril de 2021 às 04:51:53 UTC-3, José Valim escreveu: >> >>> I have been thinking more about this problem and there is still one >>> issue for us to solve: when you say you are waiting for "n" tasks, does it >>> mean you are waiting for "n" successes or "n" results (regardless if they >>> are success or failure)? >>> >>> So I thought perhaps a better solution is to introduce something called >>> Task.yield_stream/2. "yield_stream" receives an enumerable of tasks and >>> emits them as they complete. To get the first successful task you would do: >>> >>> tasks >>> |> Task.yield_stream(ordered: false, timeout: 5000) >>> |> Stream.filter(&match?({:ok, _})) >>> |> Enum.at(0) >>> >>> And this made me wonder: is there any reason why you can't use >>> Task.async_stream? >>> >>> >>> On Thu, Apr 1, 2021 at 3:59 PM José Valim <jose....@dashbit.co> wrote: >>> >>>> I don't see a reason why we wouldn't return the same order. You can >>>> easily get the ones you want by `for {task, {:ok, value}} <- result do`. >>>> Plus forcing people to iterate will remind them that they most likely need >>>> to shutdown the other tasks. >>>> >>>> On Thu, Apr 1, 2021 at 3:57 PM thia.md...@gmail.com < >>>> thia.md...@gmail.com> wrote: >>>> >>>>> > In this sense, yield_many becomes a special case of yield_first >>>>> where you want to yield on all given tasks. >>>>> >>>>> I'm not sure if we would want that, because in yield_many the returned >>>>> list will be in the same order as the tasks supplied in the tasks >>>>> input argument. >>>>> However yield_first to preserve the semantics of "returning as soon it >>>>> finishes", maybe we should return the tasks in the order of finish (the >>>>> first to complete first in the list). >>>>> That makes sense? >>>>> >>>>> Em quarta-feira, 31 de março de 2021 às 19:35:47 UTC-3, >>>>> thia.md...@gmail.com escreveu: >>>>> >>>>>> +1 for yield_first(tasks, n, timeout) >>>>>> >>>>>> It seems to better convey the meaning "yield the first n tasks". >>>>>> >>>>>> Em qua., 31 de mar. de 2021 às 19:26, Felipe Stival <v0i...@gmail.com> >>>>>> escreveu: >>>>>> >>>>>>> +1 for yield_first(tasks, n, timeout) >>>>>>> >>>>>>> >>>>>>> On Thu, Apr 1, 2021, 01:11 José Valim <jose....@dashbit.co> 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 thia.md...@gmail.com < >>>>>>>> thia.md...@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-co...@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-co...@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 >>>>>>>> <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 a topic in >>>>>>> the Google Groups "elixir-lang-core" group. >>>>>>> To unsubscribe from this topic, visit >>>>>>> https://groups.google.com/d/topic/elixir-lang-core/ZIFsisK12CM/unsubscribe >>>>>>> . >>>>>>> To unsubscribe from this group and all its topics, 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/CAKC64%2BwFh20dRTVnJi5QC8Ekk5CNcSx8k8jW_xBP65rOYGukYw%40mail.gmail.com >>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAKC64%2BwFh20dRTVnJi5QC8Ekk5CNcSx8k8jW_xBP65rOYGukYw%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 elixir-lang-co...@googlegroups.com. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/elixir-lang-core/c31c31f1-2de8-41a4-a3f3-f5b924c2ea1an%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/elixir-lang-core/c31c31f1-2de8-41a4-a3f3-f5b924c2ea1an%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/8ef87d9d-32d3-4202-9f4f-d67434d207d1n%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/8ef87d9d-32d3-4202-9f4f-d67434d207d1n%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/CAGnRm4LVS2oexZNnKt0CZHtDtiv%2BXhwycANvrZNex3L0xt_%3Dww%40mail.gmail.com.