@@ -19,6 +19,22 @@ function validateKey(key, operation) {
1919 misc . assert ( key . length < 250 , 'Key must be less than 250 characters long' ) ;
2020}
2121
22+ function validateNamespaceKey ( key , operation ) {
23+ validateKey ( key , operation ) ;
24+ misc . assert ( key . length < 230 , 'Key must be less than 230 characters long when using namespaces' ) ;
25+ }
26+
27+ function keyWithPrefix ( key , prefix ) {
28+ if ( _ . isUndefined ( prefix ) ) {
29+ // only prefix was supplied
30+ // return a curried funtion that expects the key
31+ return function ( key ) {
32+ return _ . toString ( prefix ) + '_' + key ;
33+ } ;
34+ }
35+ return _ . toString ( prefix ) + '_' + key ;
36+ }
37+
2238/**
2339 * Constructor - Initiate client
2440 */
@@ -324,14 +340,26 @@ Client.prototype.deleteMulti = function(keys, cb) {
324340 * @returns {Promise }
325341 */
326342Client . prototype . set = function ( key , val , ttl , cb ) {
327- validateKey ( key , 'set' ) ;
328-
343+ var command = 'set' ;
344+ var self = this ;
329345 if ( typeof ttl === 'function' ) {
330346 cb = ttl ;
331347 ttl = 0 ;
332348 }
349+
350+ if ( _ . isPlainObject ( ttl ) && _ . isString ( ttl . namespace ) ) {
351+ var namespace = ttl . namespace ;
352+ validateNamespaceKey ( key , command ) ;
353+
354+ return this . getNamespacePrefix ( namespace ) . then ( function ( prefix ) {
355+ key = keyWithPrefix ( key , prefix ) ;
356+ return self . run ( command , [ key , val , ttl ] , cb ) ;
357+ } ) ;
358+ }
333359
334- return this . run ( 'set' , [ key , val , ttl ] , cb ) ;
360+ validateKey ( key , command ) ;
361+
362+ return this . run ( command , [ key , val , ttl ] , cb ) ;
335363} ;
336364
337365/**
@@ -384,16 +412,34 @@ Client.prototype.gets = function(key, opts, cb) {
384412 * @returns {Promise }
385413 */
386414Client . prototype . get = function ( key , opts , cb ) {
415+ var command = 'get' ;
416+ var self = this ;
387417 if ( typeof opts === 'function' && typeof cb === 'undefined' ) {
388418 cb = opts ;
389419 opts = { } ;
390420 }
391421
422+ if ( _ . isPlainObject ( opts ) && _ . isString ( opts . namespace ) ) {
423+ var namespace = opts . namespace ;
424+ validateNamespaceKey ( key , command ) ;
425+
426+ return this . getNamespacePrefix ( namespace ) . then ( function ( prefix ) {
427+
428+ if ( _ . isArray ( key ) ) {
429+ key = _ . map ( key , keyWithPrefix ( prefix ) ) ;
430+ return this . getMulti ( key , opts , cb ) ;
431+ } else {
432+ key = keyWithPrefix ( key , prefix ) ;
433+ return self . run ( command , [ key , opts ] , cb ) ;
434+ }
435+ } ) ;
436+ }
437+
392438 if ( _ . isArray ( key ) ) {
393439 return this . getMulti ( key , opts , cb ) ;
394440 } else {
395- validateKey ( key , 'get' ) ;
396- return this . run ( 'get' , [ key , opts ] , cb ) ;
441+ validateKey ( key , command ) ;
442+ return this . run ( command , [ key , opts ] , cb ) ;
397443 }
398444} ;
399445
@@ -584,6 +630,47 @@ Client.prototype.cachedump = function(slabsId, limit, cb) {
584630 return this . run ( 'stats cachedump' , [ slabsId , limit ] , cb ) ;
585631} ;
586632
633+ /**
634+ * getNamespacePrefix() - Get prefix value for the provided namespace
635+ *
636+ * @param {String } namespace - The namespace for which prefix is to be fetched
637+ * @param {Function } [cb] - The (optional) callback called on completion
638+ * @returns {Promise }
639+ */
640+ Client . prototype . getNamespacePrefix = function ( namespace , cb ) {
641+ validateKey ( namespace ) ;
642+ var self = this ;
643+ var timestamp = _ . toNumber ( new Date ( ) ) ;
644+ var prefix = this . get ( namespace ) ;
645+
646+ return prefix . then ( function ( value ) {
647+ if ( ! value ) {
648+ // the namespace is not set
649+ return self . add ( namespace , timestamp ) ;
650+ }
651+ return value ;
652+ } ) . then ( function ( value ) {
653+ // if value is undefined it means we just
654+ // added the namespace to cache.
655+ return value || timestamp ;
656+ } ) . nodeify ( cb ) ;
657+ } ;
658+
659+
660+ /**
661+ * invalidateNamespace() - Invalidate all data for a namespace.
662+ * Warning! This does not flush the cache, but instead
663+ * relies on the unused values to expire on their own
664+ *
665+ * @param {String } namespace - The namespace to invalidate
666+ * @param {Function } [cb] - The (optional) callback called on completion
667+ * @returns {Promise }
668+ */
669+ Client . prototype . invalidateNamespace = function ( namespace , cb ) {
670+ validateKey ( namespace ) ;
671+ return this . incr ( namespace , cb ) ;
672+ } ;
673+
587674/**
588675 * version() - Get current Memcached version from the server
589676 * @param {Function } [cb] - The (optional) callback called on completion
0 commit comments