commercetools / nodejs

Everything related to the Node.js ecosystem for the commercetools platform.
https://commercetools.github.io/nodejs/
MIT License
75 stars 70 forks source link

Set fetch keepalive #1787

Closed Eomm closed 2 years ago

Eomm commented 2 years ago

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

example:

        .withHttpMiddleware({
          host: config.commercetools.host,
          fetch,
          fetchOptions: {
             agent: new https.Agent({ keepAlive: true })
          }
        })
Freyert commented 2 years ago

@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 commented 2 years ago

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!

malibeg commented 1 year ago

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)