3

I am building a client and a server side framework (NodeJs) in which I want to trace transactions. I have the ability to pass headers (transaction_id) between client and server, however, I want to be able to set the transaction_id automatically. That means that if a header is defined, a middleware should be able to read and set the transaction id in the context so that down-stream calls can read it.

Building wrappers is outside the scope of the question. What I am struggling with is being able to create a scope dynamically and storing values there.

NOTE – I am using 'strict' mode which disallows dynamic scoping in node. So need another way. NOTE – I am using Promises to make client-server calls.

ra9z
  • 73
  • 7
  • It's really difficult to understand what you are asking here. You should read the guidelines on how to ask good questions. – Robert Moskal Jun 09 '17 at 15:38

2 Answers2

4

Here is how I solved it finally –

I used CLS which allows us to keep track of dynamic scope.

Reading through all the text around CLS took a while, so here is a summary of what I did (layman terms)

NOTE - I am using NodeJs with 'strict' mode. This means I can't use dynamic scoping. Given its a production system, i'd want to keep strict mode. Hence an alternate way to achieve dynamic scoping.

1) CLS creates a dynamic context/scope. That allows us to then set / get key-value pairs that are visible only till we are within the created scope.

2) Since I am using Bluebird's Promises, CLS required me to use the patch to keep the context/scope available from within Promises. https://www.npmjs.com/package/cls-bluebird

3) Using CLS with Promises took time to figure out. Here is a great discussion on how different libraries have used CLS to produce different outcomes. https://github.com/TimBeyer/cls-bluebird/issues/6

4) This is how I used CLS (paraphrased and simplified) –

var cls = require('continuation-local-storage');
var clsbluebird = require('cls-bluebird');
var namespace = cls.createNamespace('ns');
clsbluebird( namespace );

var result;
namespace.run(function() {
  namespace.set('key', 'value');
  result = abc(); // returns 'value'
});

// versus doing –
result = abc(); // returns undefined

function abc() {
  return namespace.get('key');
}

5) Usecase – This way, I implemented basic tracing of transactions. Eg. NewRelic, Trace, etc.

ra9z
  • 73
  • 7
1

Sequelize, one of the most popular orm does this using a module continuation local storage

Hope that helps you out

Community
  • 1
  • 1
Shivam
  • 3,462
  • 1
  • 15
  • 20