autoconnection.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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 _ = require('lodash');
  18. var should = require('should');
  19. var memdb = require('../../lib');
  20. var env = require('../env');
  21. var logger = require('memdb-logger').getLogger('test', __filename);
  22. describe('autoconnection test', function(){
  23. beforeEach(env.flushdb);
  24. it('concurrent execute', function(cb){
  25. var shardId = Object.keys(env.config.shards)[0];
  26. var user1 = {_id : '1', name : 'rain', level : 0};
  27. var autoconn = null;
  28. return P.try(function(){
  29. return env.startCluster(shardId);
  30. })
  31. .then(function(){
  32. return memdb.autoConnect(env.config);
  33. })
  34. .then(function(ret){
  35. autoconn = ret;
  36. return autoconn.transaction(function(){
  37. var User = autoconn.collection('user');
  38. return User.insert(user1);
  39. }, shardId);
  40. })
  41. .then(function(){
  42. var count = 8;
  43. var delay = 0;
  44. return P.map(_.range(count), function(){
  45. delay += 10;
  46. return P.delay(delay)
  47. .then(function(){
  48. // Simulate non-atomic check and update operation
  49. // each 'thread' add 1 to user1.level
  50. return autoconn.transaction(function(){
  51. var User = autoconn.collection('user');
  52. var level = null;
  53. return P.try(function(){
  54. return User.find(user1._id, 'level');
  55. })
  56. .then(function(ret){
  57. level = ret.level;
  58. })
  59. .delay(20)
  60. .then(function(){
  61. return User.update(user1._id, {level : level + 1});
  62. });
  63. }, shardId);
  64. });
  65. })
  66. .then(function(){
  67. return autoconn.transaction(function(){
  68. var User = autoconn.collection('user');
  69. return P.try(function(){
  70. return User.find(user1._id);
  71. })
  72. .then(function(ret){
  73. // level should equal to count
  74. ret.level.should.eql(count);
  75. return User.remove(user1._id);
  76. });
  77. }, shardId);
  78. });
  79. })
  80. .then(function(){
  81. return autoconn.transaction(function(){
  82. return P.try(function(){
  83. var User = autoconn.collection('user');
  84. return User.insert(user1);
  85. }).then(function(){
  86. //Should roll back on exception
  87. throw new Error('Oops!');
  88. });
  89. }, shardId)
  90. .catch(function(e){
  91. e.message.should.eql('Oops!');
  92. });
  93. })
  94. .then(function(){
  95. return autoconn.transaction(function(){
  96. return P.try(function(){
  97. var User = autoconn.collection('user');
  98. return User.find(user1._id);
  99. })
  100. .then(function(ret){
  101. (ret === null).should.eql(true);
  102. });
  103. }, shardId);
  104. })
  105. .then(function(){
  106. return autoconn.close();
  107. })
  108. .finally(function(){
  109. return env.stopCluster();
  110. })
  111. .nodeify(cb);
  112. });
  113. it('autoconnect to multiple shards', function(cb){
  114. var autoconn = null;
  115. return P.try(function(){
  116. return env.startCluster(['s1', 's2']);
  117. })
  118. .then(function(){
  119. return memdb.autoConnect({shards : env.config.shards});
  120. })
  121. .then(function(ret){
  122. autoconn = ret;
  123. // execute in s1
  124. return autoconn.transaction(function(){
  125. var Player = autoconn.collection('player');
  126. return Player.insert({_id : 'p1', name : 'rain'});
  127. }, 's1');
  128. })
  129. .then(function(){
  130. // execute in s2
  131. return autoconn.transaction(function(){
  132. var Player = autoconn.collection('player');
  133. return Player.remove('p1');
  134. }, 's2');
  135. })
  136. .then(function(){
  137. return autoconn.close();
  138. })
  139. .finally(function(){
  140. return env.stopCluster();
  141. })
  142. .nodeify(cb);
  143. });
  144. it('findReadOnly', function(cb){
  145. var autoconn = null;
  146. return P.try(function(){
  147. return env.startCluster(['s1', 's2']);
  148. })
  149. .then(function(){
  150. return memdb.autoConnect({shards : env.config.shards});
  151. })
  152. .then(function(ret){
  153. autoconn = ret;
  154. // execute in s1
  155. return autoconn.transaction(function(){
  156. return autoconn.collection('player').insert({_id : 'p1', name : 'rain'});
  157. }, 's1');
  158. })
  159. .then(function(){
  160. // read in s2
  161. return autoconn.transaction(function(){
  162. return autoconn.collection('player').findReadOnly('p1')
  163. .then(function(player){
  164. player.name.should.eql('rain');
  165. });
  166. }, 's2');
  167. })
  168. .then(function(){
  169. // execute in s1
  170. return autoconn.transaction(function(){
  171. return autoconn.collection('player').remove('p1');
  172. }, 's1');
  173. })
  174. .then(function(){
  175. return autoconn.close();
  176. })
  177. .finally(function(){
  178. return env.stopCluster();
  179. })
  180. .nodeify(cb);
  181. });
  182. });