Comparing version 4.0.0 to 5.0.0
{ | ||
"name": "diogenes", | ||
"version": "4.0.0", | ||
"version": "5.0.0", | ||
"description": "A dependency injection framework.", | ||
@@ -38,5 +38,4 @@ "main": "src/index.js", | ||
"es6-promisify": "^6.0.0", | ||
"little-ds-toolkit": "^1.0.0", | ||
"uuid": "^3.2.1" | ||
} | ||
} |
@@ -169,7 +169,6 @@ Diogenes | ||
In this case the result will be an object with an attribute for each dependency (deps.count, deps.abstract). | ||
Once a service has been executed, the result is cached forever. | ||
Errors | ||
====== | ||
If a service returns or throws an exception, this is propagated along the execution graph. Services getting an exception as one of the dependencies, are not executed. When a service gets an exception, its state is not cached. So it can be executed again. | ||
If a service returns or throws an exception, this is propagated along the execution graph. Services getting an exception as one of the dependencies, are not executed. | ||
@@ -196,20 +195,2 @@ Using function references | ||
Caching | ||
======= | ||
When you run a service, diogenes ensures you only execute a service once. There are cases in which you want to cache the output of a service between different executions. You can do so setting the cache. | ||
```js | ||
registry | ||
.service('service1') | ||
.provides((deps) => { /* ... */ }) | ||
.setCache({ len: 1 }) | ||
``` | ||
The cache depends on the service dependencies, so you are going to use the cached value only if the dependencies didn't change. Objects are compared by reference. You can set 2 cache options: | ||
* **len**: number of cached version to store | ||
* **ttl**: time to live in ms | ||
The len is mandatory. | ||
Here's some guideline: | ||
* if you want to execute something only once set "len: 1" and ensure the dependencies are cached in the same way | ||
* for pure functions, only use "len" | ||
* for functions with side effects you can decide to not use caching, in this way they are executed every time. But you can also apply a bit of caching (if the service only READ data), in this case you should use both len and ttl. | ||
Docstring | ||
@@ -367,3 +348,2 @@ ========= | ||
name: 'A', // service name | ||
cached: true/false, // true if the service was successfully called | ||
deps: [], // list of deps | ||
@@ -453,3 +433,2 @@ doc: '...', // service documentation string | ||
name: 'A', // service name | ||
cached: true/false, // true if the service was successfully called | ||
deps: [], // list of deps | ||
@@ -456,0 +435,0 @@ doc: '...', // service documentation string |
const promisify = require('es6-promisify').promisify | ||
const LRUCache = require('little-ds-toolkit/lib/lru-cache') | ||
const getName = require('./lib/get-name') | ||
const DiogenesError = require('./lib/diogenes-error') | ||
const DepsToKey = require('./lib/deps-to-key') | ||
const depsToKey = new DepsToKey() | ||
/* | ||
@@ -39,3 +35,3 @@ Service object | ||
if (match) { | ||
return match[1].trim() | ||
return match[1] | ||
} | ||
@@ -46,3 +42,3 @@ } | ||
this._doc = '' | ||
this._deps = function () { return [] } | ||
this._deps = [] | ||
this.name = getName(nameOrFunc) | ||
@@ -60,20 +56,2 @@ if (!this.name) { | ||
Service.prototype.disableCache = function serviceDisableCache () { | ||
this.cache = undefined | ||
return this | ||
} | ||
Service.prototype.setCache = function serviceSetCache (opts) { | ||
if (typeof opts !== 'object') { | ||
throw new Error('You should pass an option object with "len" and "ttl" (optional)') | ||
} | ||
if (!('len' in opts)) { | ||
throw new Error('You should define a the length of the cache (len)') | ||
} | ||
const defaultTTL = opts.ttl | ||
const maxLen = opts.len | ||
this.cache = new LRUCache({ maxLen, defaultTTL }) | ||
return this | ||
} | ||
Service.prototype.doc = function serviceDoc (text) { | ||
@@ -83,3 +61,3 @@ if (typeof text === 'undefined') { | ||
} | ||
this._doc = text | ||
this._doc = text.trim() | ||
return this | ||
@@ -89,3 +67,3 @@ } | ||
Service.prototype.deps = function serviceDeps () { | ||
return this._deps().map(getName) | ||
return this._deps.map(getName) | ||
} | ||
@@ -98,3 +76,2 @@ | ||
doc: this.doc(), | ||
cache: this.cache ? { len: this.cache.maxLen, ttl: this.cache.defaultTTL } : false, | ||
debugInfo: this._debugInfo | ||
@@ -105,3 +82,3 @@ } | ||
Service.prototype.dependsOn = function serviceDependsOn (deps) { | ||
this._deps = typeof deps === 'function' ? deps : function () { return deps } | ||
this._deps = deps | ||
return this | ||
@@ -142,17 +119,5 @@ } | ||
const context = { id: id, service: this } | ||
if (!this.cache) { // uncached | ||
return this._func.call(context, deps) | ||
} | ||
// cached | ||
const cacheKey = depsToKey.getIdFromValues(deps) | ||
if (this.cache.has(cacheKey)) { | ||
return Promise.resolve(this.cache.get(cacheKey)) | ||
} | ||
return this._func.call(context, deps) | ||
.then((value) => { | ||
this.cache.set(cacheKey, value) | ||
return value | ||
}) | ||
} | ||
module.exports = Service |
@@ -43,158 +43,2 @@ /* eslint-env node, mocha */ | ||
describe('diogenes caching behaviour', () => { | ||
it('executes every time without cache', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeA = 0 | ||
let executeB = 0 | ||
registry.service('A') | ||
.provides(() => { | ||
executeA++ | ||
return 'A' | ||
}) | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
registry.run('B') | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeA, 1) | ||
assert.equal(executeB, 1) | ||
registry.run('B') | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeA, 2) | ||
assert.equal(executeB, 2) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('executes only once with cache', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeA = 0 | ||
let executeB = 0 | ||
registry.service('A') | ||
.provides(() => { | ||
executeA++ | ||
return 'A' | ||
}) | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
.setCache({ len: 1 }) | ||
registry.run('B') | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeA, 1) | ||
assert.equal(executeB, 1) | ||
registry.run('B') | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeA, 2) | ||
assert.equal(executeB, 1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('executes only once with cache', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeB = 0 | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
.setCache({ len: 1 }) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('executes twice with cache invalidation', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeB = 0 | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
.setCache({ len: 1 }) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
registry.run('B', { A: 'A2' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 2) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('executes only once with cache (and ttl)', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeB = 0 | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
.setCache({ len: 1, ttl: 5 }) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('executes twice with cache (and ttl)', (done) => { | ||
const registry = Diogenes.getRegistry() | ||
let executeB = 0 | ||
registry.service('B').dependsOn(['A']) | ||
.provides(() => { | ||
executeB++ | ||
return 'B' | ||
}) | ||
.setCache({ len: 1, ttl: 5 }) | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 1) | ||
setTimeout(() => { | ||
registry.run('B', { A: 'A' }) | ||
.then(res => { | ||
assert.equal(res, 'B') | ||
assert.equal(executeB, 2) | ||
done() | ||
}) | ||
}, 10) | ||
}) | ||
}) | ||
}) | ||
describe('registry', () => { | ||
@@ -288,3 +132,3 @@ let registry | ||
it('must return a service in a simple case (2 functions), dependencies are a function', (done) => { | ||
it('must return a service in a simple case (2 functions)', (done) => { | ||
registry.service('hello').provides(function (deps, next) { | ||
@@ -295,7 +139,3 @@ assert.deepEqual(deps, {}) | ||
var getDeps = function () { | ||
return ['hello'] | ||
} | ||
registry.service('world').dependsOn(getDeps).provides((deps, next) => { | ||
registry.service('world').dependsOn(['hello']).provides((deps, next) => { | ||
assert.deepEqual(deps, {hello: 'hello '}) | ||
@@ -302,0 +142,0 @@ next(undefined, deps.hello + 'world!') |
@@ -24,3 +24,2 @@ /* eslint-env node, mocha */ | ||
doc: 'to all the questions', | ||
cache: false, | ||
debugInfo: { | ||
@@ -41,3 +40,2 @@ line: 11, | ||
doc: 'to all the questions', | ||
cache: false, | ||
debugInfo: { | ||
@@ -54,3 +52,2 @@ line: 11, | ||
doc: 'the important bit', | ||
cache: false, | ||
debugInfo: { | ||
@@ -84,5 +81,4 @@ line: 15, | ||
doc: 'here is the doc string', | ||
cache: false, | ||
debugInfo: { | ||
line: 70, | ||
line: 67, | ||
functionName: 'hello', | ||
@@ -89,0 +85,0 @@ parentFunctionName: 'beforeEach', |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2
162002
20
796
451
- Removedlittle-ds-toolkit@^1.0.0
- Removedlittle-ds-toolkit@1.1.1(transitive)