cacheable 0.2.9 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/registry.js DELETED
@@ -1,170 +0,0 @@
1
- // use strict;
2
- // Global cache for constructor classes
3
-
4
- var constructors = {}
5
- var RE_JSON_TIME = /^[0-9\-]+T[0-9\:\.]+Z$/
6
-
7
- var Cacheable = require('./cacheable')
8
-
9
- var _REALNAME = Cacheable._REALNAME
10
-
11
- // default keys for wrapping model methods
12
- var DEFAULT_KEY = '{_model_}:{_fn_}:%j{0}'
13
- var DEFAULT_PROTO_KEY = '{_model_}:{id}:{_fn_}'
14
- var ERROR_DUPLICATE_REGISTRY = 'DUPLICATE_REGISTRY'
15
-
16
- function enableCache(cached) {
17
- function enableInstCache(method, key, ttl) {
18
- var cls = this
19
- var fn = isValidFunc(cls.prototype[method], method)
20
- key = key || DEFAULT_PROTO_KEY.replace('{_fn_}', method)
21
- hiddenProperty(fn, _REALNAME, fn.name || method)
22
- cls.addCacheKey(key)
23
- cls.prototype['fresh_' + method] = fn
24
- cls.prototype[method] = cached.wrap(fn, key, ttl)
25
- }
26
-
27
- return function _enableCache(method, key, ttl) {
28
- var cls = this, fn
29
- // can pass ttl as the second argument
30
- if ('number' === typeof key) {
31
- ttl = key
32
- key = null
33
- }
34
- if (method[0] === '.') {
35
- return enableInstCache.call(this, method.slice(1), key, ttl)
36
- }
37
- fn = isValidFunc(cls[method], method)
38
- key = key || DEFAULT_KEY.replace('{_fn_}', method)
39
- hiddenProperty(fn, _REALNAME, fn.name || method)
40
- cls['fresh_' + method] = fn
41
- cls[method] = cached.wrap(fn, key, ttl, cls)
42
- cls.addCacheKey(key, true)
43
- return cls[method]
44
- }
45
- }
46
-
47
- function clearCache(cached) {
48
- return function _clearCache(callback) {
49
- cached.del(this._cacheKeys, callback)
50
- }
51
- }
52
-
53
- function addCacheKey(key, isClassMethod) {
54
- if (isClassMethod) {
55
- this.classCacheKeys.push(key)
56
- } else {
57
- this.itemCacheKeys.push(key)
58
- }
59
- }
60
-
61
- /**
62
- * Revive object from a json string
63
- */
64
- function reviver(k, v) {
65
- if (v && v[_REALNAME]) {
66
- var cls = v[_REALNAME]
67
- if (cls) {
68
- if (!(cls in constructors)) {
69
- log('Constructor for %s doesn\'t exist anymore.', cls)
70
- // return a undefined, mean this object is not available anymore
71
- return
72
- }
73
- cls = constructors[cls]
74
- // remove `__cachedname` assigned to this object
75
- delete v[_REALNAME]
76
- v = new cls(v)
77
- if (v._unpickle) {
78
- v._unpickle()
79
- }
80
- }
81
- return v
82
- }
83
- if ('string' === typeof v && RE_JSON_TIME.test(v)) {
84
- // revive a date object
85
- v = new Date(v)
86
- }
87
- return v
88
- }
89
-
90
- function unpickle(value) {
91
- return JSON.parse(value, reviver)
92
- }
93
-
94
-
95
- Cacheable.prototype._initClassHelper = function() {
96
- this.helpers.enableCache = enableCache(this)
97
- this.helpers.clearCache = clearCache(this)
98
- this.helpers.addCacheKey = addCacheKey
99
- this._decode = unpickle
100
- }
101
-
102
- /**
103
- * Register constructor class for unpickle
104
- */
105
- Cacheable.prototype.register = function(cls, modelName) {
106
- modelName = modelName || cls.modelName || cls.name
107
- hiddenProperty(cls, _REALNAME, modelName)
108
- hiddenProperty(cls.prototype, _REALNAME, modelName)
109
- if (cls[_REALNAME] in constructors) {
110
- var err = new Error('Class "' + cls[_REALNAME] + '" already defined')
111
- err.code = ERROR_DUPLICATE_REGISTRY
112
- throw err
113
- }
114
- if (!this.helpers.enableCache) {
115
- this._initClassHelper()
116
- }
117
- this._extend(cls)
118
- constructors[cls[_REALNAME]] = cls
119
- }
120
-
121
-
122
- /**
123
- * Extend Model with methods to enable and clear cache
124
- */
125
- Cacheable.prototype._extend = function extendClass(cls) {
126
- var cached = this, proto = cls.prototype
127
- cls.classCacheKeys = []
128
- // default item related cache
129
- cls.itemCacheKeys = ['{_model_}:{id}']
130
- // instance cache keys
131
- Object.defineProperty(proto, '_cacheKeys', {
132
- get: function() {
133
- var self = this
134
- return cls.itemCacheKeys.map(function(item) {
135
- return cached._applykey(self, item)
136
- })
137
- }
138
- })
139
- cls.enableCache = cached.helpers.enableCache
140
- cls.addCacheKey = cached.helpers.addCacheKey
141
- proto._clearCache = cached.helpers.clearCache
142
-
143
- if ('function' != typeof proto.toJSON) {
144
- throw new Error('Cache-able class must have instance method .toJSON')
145
- }
146
- proto._toJSON = proto.toJSON
147
- proto.toJSON = function toJSON() {
148
- var obj = this._toJSON()
149
- obj[_REALNAME] = cls[_REALNAME]
150
- return obj
151
- }
152
- return cls
153
- }
154
-
155
-
156
- function hiddenProperty(where, property, value) {
157
- Object.defineProperty(where, property, { value: value });
158
- }
159
-
160
- function isValidFunc(fn, method) {
161
- if (!fn) {
162
- throw new Error('method "' + method + '" not defined')
163
- }
164
- if ('function' !== typeof fn) {
165
- throw new Error('method "' + method + '" is not a function')
166
- }
167
- return fn
168
- }
169
-
170
-
@@ -1,195 +0,0 @@
1
- var should = require('should')
2
- var LRU = require('lru-cache')
3
- var User = require('./support/user')
4
-
5
- var Cacheable = require('../')
6
-
7
- describe('Public API', function() {
8
-
9
- var client, cache
10
-
11
- describe('initialize', function() {
12
- before(function() {
13
- client = LRU()
14
- cache = new Cacheable({ client: client })
15
- })
16
-
17
- it('new and no new', function() {
18
- var cache2 = Cacheable({ client: client })
19
- cache.should.be.instanceOf(Cacheable)
20
- cache2.should.be.instanceOf(Cacheable)
21
- })
22
-
23
- it('default options', function() {
24
- cache.silent.should.equal(true)
25
- cache.prefix.should.equal('cached:')
26
- })
27
- })
28
-
29
- describe('wrap', function() {
30
- var reach = 0
31
-
32
- function foo(callback) {
33
- reach += 1
34
- return callback(null, 1)
35
- }
36
-
37
- beforeEach(function() {
38
- reach = 0
39
- client.reset()
40
- })
41
-
42
- it('fn with only callback', function(done) {
43
- var fn = cache.wrap(foo, 'foo')
44
- fn(function(err, result) {
45
- result.should.equal(1)
46
- fn(function(err, result) {
47
- result.should.equal(1)
48
- // if cache is used, `reach` will not accumulate
49
- reach.should.equal(1)
50
- done()
51
- })
52
- })
53
- })
54
-
55
- it('should have default key', function(done) {
56
- var fn = cache.wrap(function foo(arg, callback) {
57
- reach += arg.a
58
- callback(null, 1)
59
- })
60
- var arg = { a: 1 }
61
- fn(arg, function(err, result) {
62
- result.should.equal(1)
63
- // should've wrapped with default cache key: '{_fn_}:%j{0}'
64
- should.equal(cache.get('foo:{"a":1}'), result)
65
- fn(arg, function(err, result) {
66
- result.should.equal(1)
67
- reach.should.equal(1)
68
- done()
69
- })
70
- })
71
- })
72
-
73
- })
74
-
75
- describe('key replace', function() {
76
-
77
- it('should handle positional', function(done) {
78
- var fn = cache.wrap(foo, 'foor-{0}-{1}')
79
- var reach = 0
80
-
81
- fn(2, 5, function(err, result) {
82
- reach.should.equal(7)
83
- result.should.equal(3)
84
- should.equal(cache.get('foor-2-5'), result)
85
- fn(2, 5, function(err, result) {
86
- reach.should.equal(7)
87
- result.should.equal(3)
88
- done()
89
- })
90
- })
91
-
92
- function foo(arg1, arg2, callback) {
93
- reach += arg1 + arg2
94
- return callback(null, 3)
95
- }
96
- })
97
-
98
- it('should handle context', function(done) {
99
- var ctx = { hello: 'abc', again: 'def' }
100
- var fn = cache.wrap(foo, 'contexted-{hello}-{this.hello}-{this.again}', null, ctx)
101
- var reach = ''
102
-
103
- fn(1, 2, function(err, result) {
104
- reach.should.equal('abc')
105
- result.should.equal('0')
106
- should.equal(cache.get('contexted-abc-abc-def'), result)
107
- fn(1, 2, function(err, result) {
108
- reach.should.equal('abc')
109
- result.should.equal('0')
110
- done()
111
- })
112
- })
113
-
114
- function foo(arg1, arg2, callback) {
115
- reach += this.hello
116
- return callback(null, '0')
117
- }
118
- })
119
-
120
- it('should handle context', function() {
121
- })
122
-
123
- })
124
-
125
-
126
- describe('register', function() {
127
-
128
- it('cannot register twice', function() {
129
- var err
130
- cache.register(User)
131
- try {
132
- cache.register(User)
133
- } catch (e) {
134
- err = e
135
- }
136
- should.exist(err)
137
- err.code.should.equal('DUPLICATE_REGISTRY')
138
- })
139
-
140
- })
141
-
142
- })
143
-
144
- describe('Registry', function() {
145
-
146
- describe('class method', function() {
147
-
148
- it('should cache', function(done) {
149
-
150
- User.enableCache('get')
151
-
152
- User.get(1, function(err, result) {
153
- should.equal(User._called, true)
154
- User._called = 'haha'
155
- User.get(1, function(err, result) {
156
- // will remain haha, if cache is used
157
- should.equal(User._called, 'haha')
158
- result.should.be.instanceOf(User)
159
- should.equal(result.data.id, 1)
160
- done()
161
- })
162
- })
163
- })
164
-
165
- })
166
-
167
- describe('instance method', function() {
168
- var user = new User({ id: 1 })
169
-
170
- it('should cache', function(done) {
171
- User.enableCache('.articleIds')
172
- user.articleIds(function(err, result) {
173
- User._called = 'instance'
174
- user.articleIds(function(err, result) {
175
- result.should.eql([1,2,3,1])
176
- should.equal(User._called, 'instance')
177
- done()
178
- })
179
- })
180
- })
181
-
182
- it('can delete cache', function(done) {
183
- user.articleIds(function(err, result) {
184
- should.equal(User._called, 'instance')
185
- user._clearCache(function() {
186
- user.articleIds(function(err, result) {
187
- should.equal(User._called, true)
188
- done()
189
- })
190
- })
191
- })
192
- })
193
-
194
- })
195
- })
package/test/mocha.opts DELETED
@@ -1,2 +0,0 @@
1
- --timeout 200
2
- --reporter spec
@@ -1,26 +0,0 @@
1
- module.exports = User
2
-
3
- function User(data) {
4
- this.data = data
5
- this.id = data.id
6
- }
7
-
8
- User.prototype.toJSON = function() {
9
- return this.data
10
- }
11
-
12
- User.prototype.articleIds = function(callback) {
13
- User._called = true
14
- var self = this
15
- process.nextTick(function() {
16
- callback(null, [1,2,3, self.id])
17
- })
18
- }
19
-
20
- User.get = function(id, callback) {
21
- User._called = true
22
- process.nextTick(function() {
23
- callback(null, new User({ id: id }))
24
- })
25
- }
26
-