@@ -10,6 +10,7 @@ var Instance = require('./Instance');
10
10
var validate = require ( './utils/validation' ) ;
11
11
var Concoction = require ( 'concoction' ) ;
12
12
var ObjectID = require ( 'mongodb' ) . ObjectID ;
13
+ var NoOpCache = require ( './caches/NoOpCache' ) ;
13
14
14
15
15
16
( require . modules || { } ) . Model = module . exports = Model ;
@@ -76,6 +77,11 @@ function Model(database, collection, schema, options) {
76
77
enumerable : false
77
78
} ) ;
78
79
80
+ Object . defineProperty ( this , 'cache' , {
81
+ value : options . cache || new NoOpCache ( ) ,
82
+ enumerable : false
83
+ } )
84
+
79
85
80
86
var extraValidators = [ ] ;
81
87
for ( var i = 0 ; i < database . plugins . length ; i ++ ) {
@@ -167,7 +173,7 @@ Model.prototype.wrap = function (document, isNew) {
167
173
return new this . Instance ( document , isNew ) ;
168
174
} ;
169
175
170
- Model . prototype . onRetrieved = function ( results , callback , wrapper ) {
176
+ Model . prototype . onRetrieved = function ( results , callback , wrapper , options ) {
171
177
///<signature>
172
178
///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
173
179
///<param name="results" type="Object">The object retrieved from the database</param>
@@ -190,9 +196,23 @@ Model.prototype.onRetrieved = function(results, callback, wrapper) {
190
196
///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
191
197
///<param name="wrapper" type="Function">A function which converts the retrieved objects prior to submission</param>
192
198
///</signature>
199
+ ///<signature>
200
+ ///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
201
+ ///<param name="results" type="Array" elementType="Object">The objects retrieved from the database</param>
202
+ ///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
203
+ ///<param name="wrapper" type="Function">A function which converts the retrieved objects prior to submission</param>
204
+ ///<param name="options" type="Object">A set of options determining how to handle the retrieved object</param>
205
+ ///</signature>
193
206
194
207
var $ = this ;
195
- wrapper = ( wrapper !== true && wrapper ) || this . wrap . bind ( this ) ;
208
+
209
+ wrapper = wrapper || this . wrap . bind ( this ) ;
210
+ options = options || { } ;
211
+
212
+ _ . defaults ( options , {
213
+ wrap : true ,
214
+ cache : true
215
+ } ) ;
196
216
197
217
var returnArray = Array . isArray ( results ) ;
198
218
if ( ! returnArray ) results = [ results ] ;
@@ -216,12 +236,19 @@ Model.prototype.onRetrieved = function(results, callback, wrapper) {
216
236
doHook ( this . options . hooks . retrieved , target , ( function ( err ) {
217
237
if ( err ) return done ( err ) ;
218
238
219
- var wrapped = wrapper ( target ) ;
239
+ var cacheDoc = _ . cloneDeep ( target ) ;
240
+
241
+ var wrapped = options . wrap ? wrapper ( target ) : target ;
220
242
221
- doHook ( this . options . hooks . ready , wrapped , function ( err ) {
243
+ doHook ( this . options . hooks . ready , wrapped , ( function ( err ) {
222
244
if ( err ) return done ( err ) ;
223
- return done ( null , wrapped ) ;
224
- } ) ;
245
+ if ( options . cache )
246
+ return this . cache . store ( cacheDoc , function ( ) {
247
+ return done ( null , wrapped ) ;
248
+ } ) ;
249
+ else
250
+ return done ( null , wrapped ) ;
251
+ } ) . bind ( this ) ) ;
225
252
} ) . bind ( this ) ) ;
226
253
} ) . bind ( this ) ;
227
254
} , this ) , function ( err , output ) {
@@ -269,12 +296,10 @@ Model.prototype.onSaving = function(instance, changes, callback) {
269
296
}
270
297
}
271
298
272
- var $ = this ;
273
-
274
- doHook ( $ . options . hooks . saving , instance , [ changes ] , callback ) ;
299
+ doHook ( this . options . hooks . saving , instance , [ changes ] , callback ) ;
275
300
} ;
276
301
277
- Model . prototype . find = function ( conditions , wrap , callback ) {
302
+ Model . prototype . find = function ( conditions , options , callback ) {
278
303
/// <signature>
279
304
/// <summary>Gets all objects in the collection.</summary>
280
305
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
@@ -291,48 +316,54 @@ Model.prototype.find = function (conditions, wrap, callback) {
291
316
/// </signature>
292
317
/// <signature>
293
318
/// <summary>Gets all objects in the collection.</summary>
294
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
319
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
295
320
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
296
321
/// </signature>
297
322
/// <signature>
298
323
/// <summary>Finds all occurences in the collection with an _id field matching the given conditions.</summary>
299
324
/// <param name="conditions" type="Mixed">The _id field of the object to locate</param>
300
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
325
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
301
326
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
302
327
/// </signature>
303
328
/// <signature>
304
329
/// <summary>Finds all occurences in the collection which match the given conditions.</summary>
305
330
/// <param name="conditions" type="Object">The conditions which will be used to select matches</param>
306
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
331
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
307
332
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
308
333
/// </signature>
309
334
310
335
var args = Array . prototype . splice . call ( arguments , 0 ) ;
311
336
312
- conditions = { } ;
313
- wrap = true ;
337
+ conditions = null ;
338
+ options = null ;
314
339
315
340
for ( var i = 0 ; i < args . length ; i ++ ) {
316
341
if ( 'function' == typeof args [ i ] )
317
342
callback = args [ i ] ;
318
- else if ( 'boolean' == typeof args [ i ] )
319
- wrap = args [ i ] ;
320
- else
343
+ else if ( ! conditions )
321
344
conditions = args [ i ] ;
345
+ else options = args [ i ] ;
322
346
}
323
347
348
+ conditions = conditions || { } ;
349
+ options = options || { } ;
350
+ _ . defaults ( options , {
351
+ wrap : true ,
352
+ cache : true
353
+ } ) ;
354
+
324
355
var $ = this ;
325
356
if ( ! _ . isPlainObject ( conditions ) ) conditions = this . downstreamID ( conditions ) ;
326
357
this . toSource ( conditions ) ;
327
358
328
359
this . collection . find ( conditions ) . toArray ( function ( err , results ) {
329
360
if ( err ) return callback ( err ) ;
330
361
if ( ! results ) return callback ( null , null ) ;
331
- return $ . onRetrieved ( results , callback , wrap || function ( value ) { return value ; } ) ;
362
+ return $ . onRetrieved ( results , callback , options . wrap || function ( value ) { return value ; } ) ;
332
363
} ) ;
333
364
} ;
334
365
335
- Model . prototype . findOne = Model . prototype . get = function ( conditions , wrap , callback ) {
366
+ Model . prototype . findOne = Model . prototype . get = function ( conditions , options , callback ) {
336
367
/// <signature>
337
368
/// <summary>Gets a single object from the collection.</summary>
338
369
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
@@ -349,51 +380,69 @@ Model.prototype.findOne = Model.prototype.get = function (conditions, wrap, call
349
380
/// </signature>
350
381
/// <signature>
351
382
/// <summary>Gets a single object from the collection.</summary>
352
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
383
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
353
384
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
354
385
/// </signature>
355
386
/// <signature>
356
387
/// <summary>Finds the first occurence in the collection with an _id field matching the given conditions.</summary>
357
388
/// <param name="conditions" type="Mixed">The _id field of the object to locate</param>
358
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
389
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
359
390
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
360
391
/// </signature>
361
392
/// <signature>
362
393
/// <summary>Finds the first occurence in the collection which matches the given conditions.</summary>
363
394
/// <param name="conditions" type="Object">The conditions which will be used to select matches</param>
364
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
395
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
365
396
/// <param name="callback" type="Function">A function to be called with the results once they have been retrieved.</param>
366
397
/// </signature>
367
398
368
399
var args = Array . prototype . splice . call ( arguments , 0 ) ;
369
400
370
- conditions = { } ;
371
- wrap = true ;
401
+ conditions = null ;
402
+ options = null ;
372
403
373
404
for ( var i = 0 ; i < args . length ; i ++ ) {
374
405
if ( 'function' == typeof args [ i ] )
375
406
callback = args [ i ] ;
376
- else if ( 'boolean' == typeof args [ i ] )
377
- wrap = args [ i ] ;
378
- else
407
+ else if ( ! conditions )
379
408
conditions = args [ i ] ;
409
+ else options = args [ i ] ;
380
410
}
381
411
412
+ conditions = conditions || { } ;
413
+ options = options || { } ;
414
+ _ . defaults ( options , {
415
+ wrap : true ,
416
+ cache : true
417
+ } ) ;
382
418
383
- var $ = this ;
384
- if ( ! _ . isPlainObject ( conditions ) ) conditions = this . downstreamID ( conditions ) ;
385
419
420
+ var isID = ! _ . isPlainObject ( conditions ) ;
421
+
422
+ if ( isID ) conditions = this . downstreamID ( conditions ) ;
386
423
this . toSource ( conditions ) ;
387
-
388
- this . collection . findOne ( conditions , function ( err , results ) {
389
- if ( err ) return callback ( err ) ;
390
- if ( ! results ) return callback ( null , null ) ;
391
-
392
- return $ . onRetrieved ( results , callback , wrap || function ( value ) { return value ; } ) ;
393
- } ) ;
424
+
425
+ var fromDB = ( function ( ) {
426
+ this . collection . findOne ( conditions , ( function ( err , results ) {
427
+ if ( err ) return callback ( err ) ;
428
+ if ( ! results ) return callback ( null , null ) ;
429
+
430
+ return this . onRetrieved ( results , callback , null , { wrap : options . wrap , cache : options . cache } ) ;
431
+ } ) . bind ( this ) ) ;
432
+ } ) . bind ( this ) ;
433
+
434
+ if ( isID && this . cache && options . cache )
435
+ this . cache . fetch ( conditions . _id , ( function ( err , doc ) {
436
+ if ( ! err && doc )
437
+ return this . onRetrieved ( doc , callback , null , { wrap : options . wrap , cache : false } ) ;
438
+ else
439
+ return fromDB ( ) ;
440
+ } ) . bind ( this ) ) ;
441
+ else
442
+ return fromDB ( ) ;
394
443
} ;
395
444
396
- Model . prototype . insert = Model . prototype . create = function ( object , wrap , callback ) {
445
+ Model . prototype . insert = Model . prototype . create = function ( object , options , callback ) {
397
446
/// <signature>
398
447
/// <summary>Inserts the given object into the database</summary>
399
448
/// <param name="object" type="Object">The properties to set on the newly created object</param>
@@ -414,13 +463,13 @@ Model.prototype.insert = Model.prototype.create = function (object, wrap, callba
414
463
/// </signature>
415
464
/// <summary>Inserts the given object into the database</summary>
416
465
/// <param name="object" type="Object">The properties to set on the newly created object</param>
417
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
466
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
418
467
/// <param name="callback" type="Function">A function to be called once the object has been created</param>
419
468
/// </signature>
420
469
/// <signature>
421
470
/// <summary>Inserts the given object into the database</summary>
422
471
/// <param name="object" type="Array" elementType="Object">An array of objects representing the properties to set on the newly created objects</param>
423
- /// <param name="wrap " type="Boolean">Whether or not to wrap results in an Instance object </param>
472
+ /// <param name="options " type="Object">Options dictating how Iridium handles this request </param>
424
473
/// <param name="callback" type="Function">A function to be called once the objects have been created</param>
425
474
/// </signature>
426
475
@@ -429,10 +478,14 @@ Model.prototype.insert = Model.prototype.create = function (object, wrap, callba
429
478
var returnArray = true ;
430
479
431
480
if ( ! callback ) {
432
- callback = wrap ;
433
- wrap = true ;
481
+ callback = options ;
482
+ options = options || { } ;
434
483
}
435
484
485
+ _ . defaults ( options , {
486
+ wrap : true
487
+ } ) ;
488
+
436
489
if ( ! Array . isArray ( object ) ) {
437
490
object = [ object ] ;
438
491
returnArray = false ;
@@ -454,7 +507,7 @@ Model.prototype.insert = Model.prototype.create = function (object, wrap, callba
454
507
$ . collection . insert ( prepped , { w : callback ? 1 : 0 } , function ( err , inserted ) {
455
508
if ( err ) return end ( err ) ;
456
509
if ( callback )
457
- return $ . onRetrieved ( inserted , end , wrap || function ( value ) { return value ; } ) ;
510
+ return $ . onRetrieved ( inserted , end , null , options ) ;
458
511
return end ( ) ;
459
512
} ) ;
460
513
} ;
0 commit comments