slave.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2015 The MemDB Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. // implied. See the License for the specific language governing
  13. // permissions and limitations under the License. See the AUTHORS file
  14. // for names of contributors.
  15. 'use strict';
  16. var P = require('bluebird');
  17. var Logger = require('memdb-logger');
  18. var redis = P.promisifyAll(require('redis'));
  19. var utils = require('./utils');
  20. var Slave = function(opts){
  21. opts = opts || {};
  22. this.shardId = opts.shardId;
  23. this.config = {
  24. host : opts.host || '127.0.0.1',
  25. port : opts.port || 6379,
  26. db : opts.db || 0,
  27. options : opts.options || {},
  28. };
  29. this.client = null;
  30. this.logger = Logger.getLogger('memdb', __filename, 'shard:' + this.shardId);
  31. };
  32. var proto = Slave.prototype;
  33. proto.start = function(){
  34. return P.bind(this)
  35. .then(function(){
  36. this.client = redis.createClient(this.config.port, this.config.host, this.config.options);
  37. var self = this;
  38. this.client.on('error', function(err){
  39. self.logger.error(err.stack);
  40. });
  41. return this.client.selectAsync(this.config.db);
  42. })
  43. .then(function(){
  44. this.logger.info('slave started %s:%s:%s', this.config.host, this.config.port, this.config.db);
  45. });
  46. };
  47. proto.stop = function(){
  48. return P.bind(this)
  49. .then(function(){
  50. return this.client.quitAsync();
  51. })
  52. .then(function(){
  53. this.logger.info('slave stoped');
  54. });
  55. };
  56. proto.set = function(key, doc){
  57. this.logger.debug('slave set %s', key);
  58. return this.client.setAsync(this._redisKey(key), JSON.stringify(doc));
  59. };
  60. proto.del = function(key){
  61. this.logger.debug('slave del %s', key);
  62. return this.client.delAsync(this._redisKey(key));
  63. };
  64. // docs - {key : doc}
  65. proto.setMulti = function(docs){
  66. this.logger.debug('slave setMulti');
  67. var multi = this.client.multi();
  68. for(var key in docs){
  69. var doc = docs[key];
  70. multi = multi.set(this._redisKey(key), JSON.stringify(doc));
  71. }
  72. return multi.execAsync();
  73. };
  74. // returns - {key : doc}
  75. proto.getMulti = function(keys){
  76. this.logger.debug('slave getMulti');
  77. var self = this;
  78. var multi = this.client.multi();
  79. keys.forEach(function(key){
  80. multi = multi.get(self._redisKey(key));
  81. });
  82. return multi.execAsync()
  83. .then(function(results){
  84. var docs = {};
  85. for(var i in keys){
  86. var key = keys[i];
  87. if(!!results[i]){
  88. docs[key] = JSON.parse(results[i]);
  89. }
  90. }
  91. return docs;
  92. });
  93. };
  94. proto.getAllKeys = function(){
  95. this.logger.debug('slave getAllKeys');
  96. return P.bind(this)
  97. .then(function(){
  98. return this.client.keysAsync(this._redisKey('*'));
  99. })
  100. .then(function(keys){
  101. var self = this;
  102. return keys.map(function(key){
  103. return self._extractKey(key);
  104. });
  105. });
  106. };
  107. proto.clear = function(){
  108. this.logger.debug('slave clear');
  109. return P.bind(this)
  110. .then(function(){
  111. return this.client.keysAsync(this._redisKey('*'));
  112. })
  113. .then(function(keys){
  114. var multi = this.client.multi();
  115. keys.forEach(function(key){
  116. multi = multi.del(key);
  117. });
  118. return multi.execAsync();
  119. });
  120. };
  121. proto._redisKey = function(key){
  122. return 'bk$' + this.shardId + '$' + key;
  123. };
  124. proto._extractKey = function(existKey){
  125. var words = existKey.split('$');
  126. return words.slice(2, words.length).join('$');
  127. };
  128. module.exports = Slave;