nodejs icon indicating copy to clipboard operation
nodejs copied to clipboard

Set fetch keepalive

Open Eomm opened this issue 3 years ago • 2 comments
trafficstars

Support reference number

Description

I would like to set the HTTP agent keepalive to speed up the HTTP call to the CT APIs: https://github.com/node-fetch/node-fetch#custom-agent

Current code:

      const commercetoolsClient = new ClientBuilder()
        .withProjectKey(config.commercetools.auth.projectKey)
        .withHttpMiddleware({
          host: config.commercetools.host,
          fetch
        })
        .withUserAgentMiddleware()
        .build()

      const apiRoot = createApiBuilderFromCtpClient(commercetoolsClient)

Expected Behavior

Current Behavior

All works, but the customers import is slow

Context

I need to import >500k rows

Possible Solution

  • Parallelize calls (done)
  • Set the HTTP agent to keep alive the connection: should be supported by this SDK

example:

        .withHttpMiddleware({
          host: config.commercetools.host,
          fetch,
          fetchOptions: {
             agent: new https.Agent({ keepAlive: true })
          }
        })

Eomm avatar Jun 09 '22 09:06 Eomm

@Eomm we're looking into the issue, and came up with a work around that might be worth trying.

If you're in a nodejs runtime, there is a globalAgent you can adjust keepAlive settings on. I'm kind of an old school nodejs user myself so please excuse all the require.

let http = require('http')

http.globalAgent.keepAlive = true

//instantiate your middleware client afterwards.

Note, I have not actually validated that this works for nodejs, but is something I'm fairly confident should work. Though it will set all HTTP requests using the globalAgent to share connections.

Freyert avatar Jul 29 '22 20:07 Freyert

I think actually the best way to set specific fetch related options is to make a facade fetcher:

function fetcher(resource, options) {
  return fetch(resource, Object.assign(options, { "keepAlive": true })
}

...
.withHttpMiddleware({
          host: config.commercetools.host,
          fetch: fetcher
        })

@Eomm let me know if that suits you better. And remember to close the issue if you're satisfied!

Freyert avatar Aug 10 '22 13:08 Freyert

You will need to use node http agent to send kee-alive requests (to check if you traffic uses keep-alive use NODE_DEBUG=http):

import nodeFetch from "node-fetch";
import http from "http";
import https from "https";

const httpAgent = new http.Agent({ keepAlive: true });
const httpsAgent = new https.Agent({ keepAlive: true });
const agent = (parsedURL: URL) => {
  return parsedURL.protocol == "http:" ? httpAgent : httpsAgent;
};

const wrappedFetch = async (url: RequestInfo, options: RequestInit) => {
  log().debug(`Fetching with node-fetch == url: ${JSON.stringify(url)}, ${JSON.stringify(options)}`);
  return nodeFetch(url as any, Object.assign({}, options, { agent } as any));
};

 const options: HttpMiddlewareOptions = {
    host: host,
    enableRetry: true,
    fetch: wrappedFetch as unknown as typeof fetch,
  };
  ....
  .withHttpMiddleware(options)

malibeg avatar Mar 03 '23 08:03 malibeg