I wanted to do some performance testing of my site. For that purpose I wanted to fire n
requests asynchronously, combine the Futures that result of that into one future that completes when they all complete and then wait for that futures completion.
However, my code gets stuck awaiting the combined future and never completes.
My code looked like this:
import benchy
import std/[sugar, strformat, sequtils, httpclient, asyncfutures, asyncdispatch]
proc callSite(client: AsyncHttpClient, url: static string, callCount: int): Future[string] {.async.} =
var futures : seq[Future[AsyncResponse]] = @[]
for x in 1..callCount:
futures.add client.get(url)
echo "pre combo"
let comboFuture = all(futures)
let responses = await comboFuture
echo "post awaited combo"
result = await responses[0].body
echo "post response"
var myClient = newAsyncHttpClient()
myClient.headers = newHttpHeaders({
"Authorization": "Bearer " & token,
"Accept": "application/json"
})
const url = <Some URL>
timeIt "campaign overview":
let x = waitFor myClient.callSite(url, 3)
keep(x)
When I run this I never get past "pre combo"
, the request gets stuck, even though the server receives 3 requests and sends 3 responses (I checked that in server-side logs).
What is going wrong here?
CodePudding user response:
The reason for the issue is that clients from std/httpclient
do not support a client dealing with more than one request at a time!
import benchy
import std/[sugar, strformat, sequtils, httpclient, asyncfutures, asyncdispatch]
proc callSite(clients: seq[AsyncHttpClient], url: static string): Future[string] {.async.} =
var futures : seq[Future[AsyncResponse]] = @[]
for client in clients:
futures.add client.get(url)
let comboFuture = all(futures)
let responses = await comboFuture
result = await responses[0].body
proc createMyClient(): AsyncHttpClient =
result = newAsyncHttpClient()
result.headers = newHttpHeaders({
"Authorization": "Bearer " & token,
"Accept": "application/json"
})
let fiftyClients: seq[AsyncHttpClient] = (1..50).toSeq().mapIt(createMyClient())
const url = <Some Url>
timeIt "50 client":
let x = waitFor fiftyClients.callSite(url)
keep(x)