#what is the best way to maintain context on the backend?

22 messages · Page 1 of 1 (latest)

atomic cedar
#

I have a scenario where I want each user to have its own session ID, this session ID will be stored with certain parameters that affect the user's request.
what would be the best way to achieve this ?
I want o hold a session id that is available throughout the flow
I want it to be available in every function in the flow, so what should I do ?
Even in functions that are not necessarily part of the nestjs app that I am working on

One option that is that I can propagate it on every function call, but I want something elegant

gaunt relic
#

You can set a custom property on user request object or else set an object of different important properties like tokens, session id , role etc

#

Go through this blog , i think this is perfect solution for your problem still if you are stuck ping me if i am available I will surely help @atomic cedar

scarlet ore
#

@atomic cedar As of a few versions ago, node supports AsyncLocalStorage, which allows you to store data and retrieve it in any code that's running as part of the same callback/promise chain.

#

It's essentially a node equivalent to "thread local storage" which you might be familiar with from other languages.

atomic cedar
#

lets say I have a function A that along its call stack calling function K
does function K have access to the variables that are part of the call stack from A->K ?

scarlet ore
#

It has access to anything specifically put into AsyncLocalStorage.

#

So for the case you describe, you'd put the session id into AsyncLocalStorage when the request comes in and any logic for handling that request should be able to retrieve the session id.

atomic cedar
#

so I do need to propagate the session id down the call stack ?

scarlet ore
#

No, you put it into AsyncLocalStorage in one place and retrieve it somewhere else.

atomic cedar
#

I just wonder if there is anything similar to what opentelemetry is doing
they somehow maintain the same traceId throughout the flow

scarlet ore
#

AsyncLocalStorage is a global API.

atomic cedar
#

what happens if 2 requests come at the same time
do I create an instance of it on each request ?

#

and each request will have its own asyncLocalStorage ? that is retreivable ?

scarlet ore
#

Each request has it's own store inside the async local storage, yeah.

atomic cedar
#

interesting

#

I will try to see how it behaves

#

do I need to export the specific instance ?
or if I just import it and use it then it will maintain the context ?

scarlet ore
#

There's an example on the documentation I linked which may help.

#
const http = require('node:http');
const { AsyncLocalStorage } = require('node:async_hooks');

const asyncLocalStorage = new AsyncLocalStorage();

function logWithId(msg) {
  const id = asyncLocalStorage.getStore();
  console.log(`${id !== undefined ? id : '-'}:`, msg);
}

let idSeq = 0;
http.createServer((req, res) => {
  asyncLocalStorage.run(idSeq++, () => {
    logWithId('start');
    // Imagine any chain of async operations here
    setImmediate(() => {
      logWithId('finish');
      res.end();
    });
  });
}).listen(8080);

http.get('http://localhost:8080');
http.get('http://localhost:8080');
// Prints:
//   0: start
//   1: start
//   0: finish
//   1: finish