Home > Enterprise >  Nodejs: Responding synchronously to a request by calling an asynchronous service
Nodejs: Responding synchronously to a request by calling an asynchronous service

Time:05-13

I'm writing a Nodejs based service, N, that sits between entities A and B.

A <----> N <----> B

App A POSTs a synchronous request to N, which N must respond to with data it can only get by calling an external service B.

The problem is, B is an asynchronous service/API: Anything N POSTs to B is responded to first with an HTTP 202 ("request accepted"), and then later with the actual data as a callback POST request from B to N. So, essentially, inside the single-threaded N, I have to somehow keep the current, synchronous request from A "on hold" without blocking other potential requests from A to N while the asynchronous message exchange between N and B completes to service the request from A currently on hold.

Is this possible in Nodejs, say, using promises or async/await magic?

CodePudding user response:

With request id, local cache & timeout, you could do something like this:


const requestIdAndResponseDetailsMap = {};


router.post('/request-from-a', function requestFromAHandler(request, response) {

  const requestId = request.body.id;
  makeCallToB(request.body); // ensure that request id is passed to B and sent in the call from B to N.
  cacheServiceAResponseWithTimeout(requestId, response);

});

router.post('/callback-from-b', function callbackFromBHandler(request, response) {

  const dataFromB = request.body;

  tryRespondToA(dataFromB);

  response.json({ success: true });

});

function tryRespondToA(responseFromB) {
  const requestId = responseFromB.id;
  const cachedData = requestIdAndResponseDetailsMap[requestId];

  if(cachedData === undefined) {
    return;
  }
  delete requestIdAndResponseDetailsMap[requestId];
  clearTimeout(cachedData.timerReference);
  cachedData.response.json(responseFromB);
  
}

function cacheServiceAResponseWithTimeout(requestId, response) {
  
  const timerReference = setTimeout(function timerCallback() {
    const cachedData = requestIdAndResponseDetailsMap[requestId];
    delete requestIdAndResponseDetailsMap[requestId];
    cachedData.response.json({ message: 'Service B request timed out' });
  }, TIMEOUT_IN_MILLISECONDS);

  requestIdAndResponseDetailsMap[requestId] = { response, timerReference };

}


  • Related