From 3004e14cb9429ede7daf1ce14a134ec67605af2f Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Sat, 9 Apr 2016 13:15:49 +0100 Subject: [PATCH] Initial release --- README.md | 35 +++++++++++++++++++++++++++++++++++ changelog.md | 2 ++ lib/index.js | 28 ++++++++++++++++++++++++++-- package.json | 1 + test/all.test.js | 33 ++++++++++++++++++++++++++++++--- 5 files changed, 94 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 108f4b8..4ca99fc 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,41 @@ ## Usage +Runs a callback asynchronously, but *outside* of current CLS context. + +### loseCls( callback ) + +`callback` is called in next tick. As opposed to `setImmediate`, `process.nextTick()` etc, the [continuation-local-storage](https://www.npmjs.com/package/continuation-local-storage) context is not maintained. + +### Why? + +Primarily, this module exists to facilitate testing of node.js libraries / applications that use [continuation-local-storage](https://www.npmjs.com/package/continuation-local-storage). + +This module is a lightweight way to test what happens when CLS context is lost (which many libraries e.g. `redis` do) and to ensure that your own code handles this correctly, perhaps by re-binding with `namespace.bind()`. + +### Example + +```js +var cls = require('continuation-local-storage'); +var namespace = cls.createNamespace('test'); + +var loseCls = require('lose-cls-context'); + +namespace.run(function() { + namespace.set('value', 123); + + setImmediate(function() { + var value = namespace.get('value'); + // CLS context is maintained - value === 123 + }); + + loseCls(function() { + var value = namespace.get('value'); + // CLS context has been lost - value === undefined + }); +}); +``` + ## Tests Use `npm test` to run the tests. Use `npm run cover` to check coverage. diff --git a/changelog.md b/changelog.md index 57855bc..94a1afe 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,5 @@ # Changelog ## Next + +* Initial release diff --git a/lib/index.js b/lib/index.js index f6811ca..83ab3cf 100644 --- a/lib/index.js +++ b/lib/index.js @@ -2,6 +2,30 @@ // lose-cls-context module // -------------------- -// exports -module.exports = function() { +// init queue +var queue = []; + +// runs fns in queue +function clearQueue() { + // get item at front of queue and call fn + var fn = queue.shift(); + if (fn) fn(); + + // run again on next tick + clearQueueLater(); +} + +// schedules running fns in queue on next tick +function clearQueueLater() { + setImmediate(clearQueue); +} + +// start running queue +clearQueueLater(); + +// add fn to queue +module.exports = function(fn) { + if (!fn || typeof fn != 'function') throw new Error('fn must be a function'); + + queue.push(fn.bind(this)); }; diff --git a/package.json b/package.json index 82be145..28503de 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "url": "https://github.com/overlookmotel/lose-cls-context/issues" }, "dependencies": { + "continuation-local-storage": "^3.1.6" }, "devDependencies": { "mocha": "^2.4.5", diff --git a/test/all.test.js b/test/all.test.js index 20dad9f..df1ab27 100644 --- a/test/all.test.js +++ b/test/all.test.js @@ -8,16 +8,43 @@ var chai = require('chai'), expect = chai.expect, lose = require('../lib/'); +var cls = require('continuation-local-storage'); + // init chai.config.includeStack = true; +// init CLS +var namespace = cls.createNamespace('test'); + // tests /* jshint expr: true */ /* global describe, it */ -describe('Tests', function() { - it.skip('all', function() { - expect(lose).to.be.ok; +describe('lose-cls-context', function() { + it('calls fn asynchronously', function(done) { + var order = []; + + lose(function() { + order.push('cb'); + + expect(order).to.deep.equal(['after', 'cb']); + + done(); + }); + + order.push('after'); + }); + + it('loses CLS context', function(done) { + namespace.run(function() { + namespace.set('value', 123); + + lose(function() { + var value = namespace.get('value'); + expect(value).to.not.equal(123); + done(); + }); + }); }); });