Skip to content

Commit a3805d7

Browse files
author
Alexander Mays
committed
Clean up, added documentation. Moved resolveAdapter to the provider
Signed-off-by: Alexander Mays <[email protected]>
1 parent 3baf29d commit a3805d7

File tree

9 files changed

+185
-46
lines changed

9 files changed

+185
-46
lines changed

Auth.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
var deepcopy = require('deepcopy');
22
var Parse = require('parse/node').Parse;
33
var RestQuery = require('./RestQuery');
4+
var CacheProvider = require('./classes/CacheProvider');
45

56
// An Auth object tells you who is requesting something and whether
67
// the master key was used.
@@ -41,7 +42,7 @@ function nobody(config) {
4142

4243
// Returns a promise that resolves to an Auth object
4344
var getAuthForSessionToken = function(config, sessionToken) {
44-
var cache = require('./classes/CacheProvider').getAdapter();
45+
var cache = CacheProvider.getAdapter();
4546

4647
var cachedUser = cache.get(sessionToken);
4748
if (cachedUser) {

classes/BaseProvider.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
var ServiceProviderInterface = require('../interfaces/ServiceProvider');
22
var util = require('util');
33

4+
/**
5+
* A base provider class that allows for an abstraction of adapter implementations
6+
*
7+
* @class
8+
* @implements {ServiceProvider}
9+
* @param {Object} adapter - An adapter
10+
*/
411
function BaseProvider(adapter) {
512
if (adapter) {
613
this.adapter = adapter;
@@ -9,16 +16,47 @@ function BaseProvider(adapter) {
916

1017
util.inherits(BaseProvider, ServiceProviderInterface);
1118

19+
/**
20+
* Get the adapter
21+
*
22+
* @returns {Object} An adapter instance
23+
*/
1224
function getAdapter() {
1325
return this.adapter;
1426
}
1527

28+
/**
29+
* Set the adapter
30+
*
31+
* @param {Object} adapter - An adapter
32+
*/
1633
function setAdapter(adapter) {
1734
this.adapter = adapter;
1835
}
1936

37+
/**
38+
* Resolves the adapter
39+
*
40+
* @param {Object|String|Function} adapter - [1] An object implementing the adapter interface, or [2] a function that returns [1], or [3] A string of either the name of an included npm module or a path to a local module that returns [1] or [2].
41+
* @param {Object} options - An object passed to the adapter on instantiation (if adapter is not already instantiated)
42+
* @returns {Object} An object implementing the adapter interface
43+
*/
44+
function resolveAdapter(adapter, options) {
45+
// Support passing in adapter paths
46+
if (typeof adapter === 'string') {
47+
adapter = require(adapter);
48+
}
49+
50+
// Instantiate the adapter if the class got passed instead of an instance
51+
if (typeof adapter === 'function') {
52+
adapter = new adapter(options);
53+
}
54+
55+
return adapter;
56+
}
57+
2058
BaseProvider.prototype.getAdapter = getAdapter;
2159
BaseProvider.prototype.setAdapter = setAdapter;
22-
BaseProvider.prototype.BaseProvider = BaseProvider;
60+
BaseProvider.prototype.resolveAdapter = resolveAdapter;
2361

24-
exports = module.exports = new BaseProvider();
62+
exports = module.exports = BaseProvider;

classes/CacheProvider.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
1-
var BaseProvider = require('./BaseProvider').BaseProvider;
21
var util = require('util');
32

3+
var BaseProvider = require('./BaseProvider');
4+
var DefaultCacheAdapter = require('./MemoryCache');
5+
6+
/**
7+
* Abstract class the provides a reference to an adapter instance (a caching implementation)
8+
*
9+
* @class
10+
* @extends {BaseProvider}
11+
* @param {Object} adapter - A cache adapter
12+
*/
413
function CacheProvider(adapter) {
514
CacheProvider.super_.call(this)
615
};
716

17+
/**
18+
* Setup the cache provider given a configuration object
19+
*
20+
* @method
21+
* @param {Object} config - A configuration object
22+
* @param {Any} config.adapter - A string, object, instance, or function that resolves to an adapter implementation
23+
* @param {Object} config.options - An object passed to the adapter on instantiation (if adapter is not already instantiated)
24+
*/
25+
function setup (config) {
26+
config = config || {};
27+
config.adapter = config.adapter || DefaultCacheAdapter;
28+
29+
var adapter = this.resolveAdapter(config.adapter, config.options);
30+
this.setAdapter(adapter);
31+
}
32+
833
util.inherits(CacheProvider, BaseProvider);
934

35+
CacheProvider.prototype.setup = setup;
1036
CacheProvider.prototype.CacheProvider = CacheProvider;
1137

1238
exports = module.exports = new CacheProvider();

classes/MemoryCache.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
'use strict';
22
// Modified from https://github.com/ptarjan/node-cache/blob/master/index.js
3+
4+
/**
5+
* Creates a new in-memory cache using Map for storage
6+
*
7+
* @class
8+
* @param {Object} options - An object of default options
9+
* @param {String} [options.defaultTtl=600000] - The number of milliseconds to use as the default time-to-live of a cache entry
10+
*/
311
function MemoryCache(options) {
412
options = options || {};
513

@@ -10,6 +18,15 @@ function MemoryCache(options) {
1018
this.defaultTtl = options.defaultTtl || 10 * 60 * 1000;
1119
};
1220

21+
/**
22+
* Puts a key value mapping into the map that will automatically expire given a TTL.
23+
* @method put
24+
* @param {String} key - A unique key
25+
* @param {Any} value - A value to be stored
26+
* @param {Number} ttl - The number of milliseconds until the key/value pair is removed from the cache
27+
* @param {Function} timeoutCallback - A callback that is fired on expiration (post removal)
28+
* @returns {Object} The MemoryCache instance
29+
*/
1330
function put (key, value, ttl, timeoutCallback) {
1431
if (this.debug) {
1532
console.log('caching: %s = %j (@%s)', key, value, ttl);
@@ -50,6 +67,12 @@ function put (key, value, ttl, timeoutCallback) {
5067
return value;
5168
};
5269

70+
/**
71+
* Deletes a key/value pair from the cache
72+
* @method del
73+
* @param {String} key - A unique key
74+
* @returns {Boolean} True if a record was removed from the cache (a hit) or false if the record was not found (a miss)
75+
*/
5376
function del (key) {
5477
if (this.debug) {
5578
console.log('Deleting key ', key);
@@ -67,6 +90,10 @@ function del (key) {
6790
return false;
6891
};
6992

93+
/**
94+
* Resets the cache to it's original state
95+
* @method clear
96+
*/
7097
function clear () {
7198
for (var entry of this.cache) {
7299
clearTimeout(entry[1].timeout);
@@ -76,13 +103,24 @@ function clear () {
76103
this.missCount = 0;
77104
};
78105

106+
/**
107+
* Disables a timer (timeout/expiration) for a specifiy key/value pair
108+
* @method killTimer
109+
* @param {String} key - A unique key
110+
*/
79111
function killTimer(key) {
80112
var obj = this.cache.get(key);
81113
if (obj && obj.timeout) {
82114
clearTimeout(obj.timeout);
83115
}
84116
};
85117

118+
/**
119+
* Retrieves a value given a key from the cache
120+
* @method get
121+
* @param {String} key - A unique key
122+
* @returns {Any|undefined} Returns the value for the key in the cache or undefined if not found
123+
*/
86124
function get (key) {
87125
var data = this.cache.get(key);
88126
if (typeof data != "undefined") {
@@ -100,30 +138,61 @@ function get (key) {
100138
return undefined;
101139
};
102140

141+
/**
142+
* @method size
143+
* @returns {Number} The number of key/value pairs in the cache
144+
*/
103145
function size () {
104146
return this.cache.size;
105147
};
106148

149+
/**
150+
* Toggles debug statements
151+
* @method setDebug
152+
* @param {Boolean} bool - The value to set debug
153+
*/
107154
function setDebug (bool) {
108155
this.debug = bool;
109156
};
110157

158+
/**
159+
* @method hits
160+
* @returns {Number} The number of values successfully retrieved via get()
161+
*/
111162
function hits () {
112163
return this.hitCount;
113164
};
114165

166+
/**
167+
* @method misses
168+
* @returns {Number} The number of unsuccessfully get attempts
169+
*/
115170
function misses () {
116171
return this.missCount;
117172
};
118173

174+
/**
175+
* @method keys
176+
* @returns {Array} An array of all the keys in the map
177+
*/
119178
function keys () {
120179
return Array.from(this.cache.keys());
121180
};
122181

182+
/**
183+
* @method toArray
184+
* @returns {Array} An array of all the values in the map
185+
*/
123186
function toArray() {
124187
return Array.from(this.cache.values());
125188
}
126189

190+
/**
191+
* @method map
192+
* @param {Function} functor - A function that transforms a value for a given key/value pair
193+
* @param {Object} context - The context for the functor call
194+
* @returns {Map} A map containing key/value pairs where the original value was transformed by the provided functor
195+
*/
127196
function map(functor, context) {
128197
context = context || this;
129198
var result = new Map();
@@ -137,6 +206,12 @@ function map(functor, context) {
137206
return result;
138207
}
139208

209+
/**
210+
* @method filter
211+
* @param {Function} predicate - A filter function
212+
* @param {Object} context - The context for the predicate call
213+
* @returns {Map} A map containing truthy results of a provided filter function
214+
*/
140215
function filter(predicate, context) {
141216
context = context || this;
142217
var result = new Map();

index.js

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,13 @@ addParseCloud();
3939
// "restAPIKey": optional key from Parse dashboard
4040
// "javascriptKey": optional key from Parse dashboard
4141

42-
var DefaultCacheAdapter = require('./classes/MemoryCache');
43-
4442
function ParseServer(args) {
4543
if (!args.appId || !args.masterKey) {
4644
throw 'You must provide an appId and masterKey!';
4745
}
4846

49-
this.setupCache(args.cache);
50-
51-
var cache = this.cacheProvider.getAdapter();
47+
// Setup providers
48+
CacheProvider.setup(args.cache);
5249

5350
if (args.databaseAdapter) {
5451
DatabaseAdapter.setAdapter(args.databaseAdapter);
@@ -66,7 +63,7 @@ function ParseServer(args) {
6663
} else if (typeof args.cloud === 'string') {
6764
require(args.cloud);
6865
} else {
69-
throw "argument 'cloud' must either be a string or a function";
66+
throw new Error("argument 'cloud' must either be a string or a function");
7067
}
7168

7269
}
@@ -87,11 +84,14 @@ function ParseServer(args) {
8784
appInfo['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
8885
}
8986

87+
// Cache the application information indefinitely
88+
var cache = CacheProvider.getAdapter();
9089
cache.put(args.appId, appInfo, Infinity);
9190

9291
// Initialize the node client SDK automatically
9392
Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey);
94-
if(args.serverURL) {
93+
94+
if (args.serverURL) {
9595
Parse.serverURL = args.serverURL;
9696
}
9797

@@ -175,33 +175,6 @@ function getClassName(parseClass) {
175175
return parseClass;
176176
}
177177

178-
function resolveAdapter(adapter, options) {
179-
// Support passing in adapter paths
180-
if (typeof adapter === 'string') {
181-
adapter = require(adapter);
182-
}
183-
184-
// Instantiate the adapter if the class got passed instead of an instance
185-
if (typeof adapter === 'function') {
186-
adapter = new adapter(options);
187-
}
188-
189-
return adapter;
190-
}
191-
192-
// TODO: Add configurable TTLs for cache entries
193-
function setupCache(config) {
194-
config = config || {};
195-
config.adapter = config.adapter || DefaultCacheAdapter;
196-
197-
var adapter = this.resolveAdapter(config.adapter, config.options);
198-
CacheProvider.setAdapter(adapter);
199-
this.cacheProvider = CacheProvider;
200-
}
201-
202-
ParseServer.prototype.setupCache = setupCache;
203-
ParseServer.prototype.resolveAdapter = resolveAdapter;
204-
205178
module.exports = {
206179
ParseServer: ParseServer,
207180
S3Adapter: S3Adapter

interfaces/ServiceProvider.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1-
function ServiceProviderInterface() {
1+
/**
2+
* Interface for service providers
3+
*
4+
* @interface
5+
*/
6+
function ServiceProvider() {
27
};
38

4-
ServiceProviderInterface.prototype.getAdapter = function() {
9+
/**
10+
* Get the adapter
11+
*
12+
* @returns {Object} An adapter instance
13+
*/
14+
ServiceProvider.prototype.getAdapter = function() {
515
throw new Error('A service provider must implement getAdapter!');
616
}
717

8-
ServiceProviderInterface.prototype.setAdapter = function() {
18+
/**
19+
* Set the adapter
20+
*
21+
* @param {Object} An adapter
22+
*/
23+
ServiceProvider.prototype.setAdapter = function() {
924
throw new Error('A service provider must implement setAdapter!');
1025
}
1126

12-
exports = module.exports = ServiceProviderInterface;
27+
/**
28+
* Resolves the adapter from the first parameter
29+
*
30+
* @param {Any}
31+
*/
32+
ServiceProvider.prototype.resolveAdapter = function() {
33+
throw new Error('A service provider must implement resolveAdapter!');
34+
}
35+
36+
exports = module.exports = ServiceProvider;

0 commit comments

Comments
 (0)