devfabiofreitas

devfabiofreitas

Task for requests HTTP

hello, i have the following problem:

I need to make http requests for a given site with thousands of pages. just stop the requests when the response returns {_page,}

I was able to make the code without using concurrency, and Tesla for requests

def fetch(page) do
   {:ok, response} = get(“/api/res”, query: [page: page])
   {page, response.body[“res”]}
end

def fetchAll(curr \\ 1 , list \\ ) do
  result = fetch(curr)
  case result do
   {_page, } →
      list
   {curr, nil} →
      fetchAll(curr,list)
   {_page, res} →
       curr = curr + 1
       fetchAll(curr,list++res)
  end
end

however I wanted to use Task to increase speed, but i don’t know how to do it.

if the number of pages was known, it would be easy to implement it using Task.async_stream

1..numberPages
|> Task.async_stream(fn page ->fetch(page) end, ordered: false,
max_concurrency: System.schedulers_online()*3)
|> Enum.reduce(, fn {:ok, {_page, res}}, j → res++ j end)

but as the number of pages depends on the return of the request, I don’t know how to do this

Most Liked

ruslandoga

ruslandoga

You can use Stream.reduce_while and halt when you receive {_page,[]}. Doesn’t seem like Stream.reduce_while exists. Maybe Task.async_stream and followed by Stream.take_while/2 would work.

You can use send requests in chunks and stop when you have {_page,[]} meaning you’d “overshoot” and make requests to the pages that don’t exist by that’s probably not a big problem.

Last Post!

lud

lud

You could try to find the last cursor first with a binary search: try page 1 then multiply the cursor by two until it returns []: 1, 2, 4, 8, 16, 34, 64, etc.. For instance you know that cursor 512 returned pages but 1024 returned []. Then you try in the middle: 768. If it returns [], the last page is between 512 and 768, if not the last page is between 768 and 1024. And you continue by trying in the new middle until you find the last cursor.

Then you can fetch all your pages from 1 to last cursor in an async stream.

Where Next?

Popular in Questions Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement