SentinelReplicationTest.php 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis\Connection\Replication;
  11. use Predis\Command;
  12. use Predis\Connection;
  13. use Predis\Replication;
  14. use Predis\Response;
  15. use PredisTestCase;
  16. /**
  17. *
  18. */
  19. class SentinelReplicationTest extends PredisTestCase
  20. {
  21. /**
  22. * @group disconnected
  23. * @expectedException Predis\ClientException
  24. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  25. */
  26. public function testMethodGetSentinelConnectionThrowsExceptionOnEmptySentinelsPool()
  27. {
  28. $replication = $this->getReplicationConnection('svc', array());
  29. $replication->getSentinelConnection();
  30. }
  31. /**
  32. * @group disconnected
  33. */
  34. public function testParametersForSentinelConnectionShouldNotUseDatabaseAndPassword()
  35. {
  36. $replication = $this->getReplicationConnection('svc', array(
  37. 'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret',
  38. ));
  39. $parameters = $replication->getSentinelConnection()->getParameters()->toArray();
  40. $this->assertArraySubset(array('database' => null, 'password' => null), $parameters);
  41. }
  42. /**
  43. * @group disconnected
  44. */
  45. public function testParametersForSentinelConnectionHaveDefaultTimeout()
  46. {
  47. $replication = $this->getReplicationConnection('svc', array(
  48. 'tcp://127.0.0.1:5381?alias=sentinel',
  49. ));
  50. $parameters = $replication->getSentinelConnection()->getParameters()->toArray();
  51. $this->assertArrayHasKey('timeout', $parameters);
  52. $this->assertSame(0.100, $parameters['timeout']);
  53. }
  54. /**
  55. * @group disconnected
  56. */
  57. public function testParametersForSentinelConnectionCanOverrideDefaultTimeout()
  58. {
  59. $replication = $this->getReplicationConnection('svc', array(
  60. 'tcp://127.0.0.1:5381?alias=sentinel&timeout=1',
  61. ));
  62. $parameters = $replication
  63. ->getSentinelConnection()
  64. ->getParameters()
  65. ->toArray();
  66. $this->assertArrayHasKey('timeout', $parameters);
  67. $this->assertSame('1', $parameters['timeout']);
  68. }
  69. /**
  70. * @group disconnected
  71. */
  72. public function testConnectionParametersInstanceForSentinelConnectionIsNotModified()
  73. {
  74. $originalParameters = Connection\Parameters::create(
  75. 'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret'
  76. );
  77. $replication = $this->getReplicationConnection('svc', array($originalParameters));
  78. $parameters = $replication
  79. ->getSentinelConnection()
  80. ->getParameters();
  81. $this->assertSame($originalParameters, $parameters);
  82. $this->assertNotNull($parameters->password);
  83. $this->assertNotNull($parameters->database);
  84. }
  85. /**
  86. * @group disconnected
  87. */
  88. public function testMethodGetSentinelConnectionReturnsFirstAvailableSentinel()
  89. {
  90. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  91. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  92. $sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?alias=sentinel3');
  93. $replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2, $sentinel3));
  94. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  95. }
  96. /**
  97. * @group disconnected
  98. */
  99. public function testMethodAddAttachesMasterOrSlaveNodesToReplication()
  100. {
  101. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  102. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  103. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  104. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  105. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  106. $replication->add($master);
  107. $replication->add($slave1);
  108. $replication->add($slave2);
  109. $this->assertSame($master, $replication->getConnectionById('master'));
  110. $this->assertSame($slave1, $replication->getConnectionById('slave1'));
  111. $this->assertSame($slave2, $replication->getConnectionById('slave2'));
  112. $this->assertSame($master, $replication->getMaster());
  113. $this->assertSame(array($slave1, $slave2), $replication->getSlaves());
  114. }
  115. /**
  116. * @group disconnected
  117. */
  118. public function testMethodRemoveDismissesMasterOrSlaveNodesFromReplication()
  119. {
  120. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  121. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  122. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  123. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  124. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  125. $replication->add($master);
  126. $replication->add($slave1);
  127. $replication->add($slave2);
  128. $this->assertTrue($replication->remove($slave1));
  129. $this->assertFalse($replication->remove($sentinel1));
  130. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  131. $this->assertCount(1, $slaves = $replication->getSlaves());
  132. $this->assertSame('127.0.0.1:6383', (string) $slaves[0]);
  133. }
  134. /**
  135. * @group disconnected
  136. */
  137. public function testMethodUpdateSentinelsFetchesSentinelNodes()
  138. {
  139. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  140. $sentinel1
  141. ->expects($this->once())
  142. ->method('executeCommand')
  143. ->with($this->isRedisCommand(
  144. 'SENTINEL', array('sentinels', 'svc')
  145. ))
  146. ->will($this->returnValue(
  147. array(
  148. array(
  149. 'name', '127.0.0.1:5382',
  150. 'ip', '127.0.0.1',
  151. 'port', '5382',
  152. 'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
  153. 'flags', 'sentinel',
  154. ),
  155. array(
  156. 'name', '127.0.0.1:5383',
  157. 'ip', '127.0.0.1',
  158. 'port', '5383',
  159. 'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
  160. 'flags', 'sentinel',
  161. ),
  162. )
  163. ));
  164. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  165. $replication->updateSentinels();
  166. // TODO: sorry for the smell...
  167. $reflection = new \ReflectionProperty($replication, 'sentinels');
  168. $reflection->setAccessible(true);
  169. $expected = array(
  170. array('host' => '127.0.0.1', 'port' => '5381'),
  171. array('host' => '127.0.0.1', 'port' => '5382'),
  172. array('host' => '127.0.0.1', 'port' => '5383'),
  173. );
  174. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  175. $this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
  176. }
  177. /**
  178. * @group disconnected
  179. */
  180. public function testMethodUpdateSentinelsRemovesCurrentSentinelAndRetriesNextOneOnFailure()
  181. {
  182. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  183. $sentinel1
  184. ->expects($this->once())
  185. ->method('executeCommand')
  186. ->with($this->isRedisCommand(
  187. 'SENTINEL', array('sentinels', 'svc')
  188. ))
  189. ->will($this->throwException(
  190. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  191. ));
  192. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  193. $sentinel2
  194. ->expects($this->once())
  195. ->method('executeCommand')
  196. ->with($this->isRedisCommand(
  197. 'SENTINEL', array('sentinels', 'svc')
  198. ))
  199. ->will($this->returnValue(
  200. array(
  201. array(
  202. 'name', '127.0.0.1:5383',
  203. 'ip', '127.0.0.1',
  204. 'port', '5383',
  205. 'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
  206. 'flags', 'sentinel',
  207. ),
  208. )
  209. ));
  210. $replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2));
  211. $replication->updateSentinels();
  212. // TODO: sorry for the smell...
  213. $reflection = new \ReflectionProperty($replication, 'sentinels');
  214. $reflection->setAccessible(true);
  215. $expected = array(
  216. array('host' => '127.0.0.1', 'port' => '5382'),
  217. array('host' => '127.0.0.1', 'port' => '5383'),
  218. );
  219. $this->assertSame($sentinel2, $replication->getSentinelConnection());
  220. $this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
  221. }
  222. /**
  223. * @group disconnected
  224. * @expectedException Predis\ClientException
  225. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  226. */
  227. public function testMethodUpdateSentinelsThrowsExceptionOnNoAvailableSentinel()
  228. {
  229. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  230. $sentinel1
  231. ->expects($this->once())
  232. ->method('executeCommand')
  233. ->with($this->isRedisCommand(
  234. 'SENTINEL', array('sentinels', 'svc')
  235. ))
  236. ->will($this->throwException(
  237. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  238. ));
  239. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  240. $replication->updateSentinels();
  241. }
  242. /**
  243. * @group disconnected
  244. */
  245. public function testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes()
  246. {
  247. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  248. $sentinel1
  249. ->expects($this->exactly(3))
  250. ->method('executeCommand')
  251. ->withConsecutive(
  252. $this->isRedisCommand('SENTINEL', array('sentinels', 'svc')),
  253. $this->isRedisCommand('SENTINEL', array('get-master-addr-by-name', 'svc')),
  254. $this->isRedisCommand('SENTINEL', array('slaves', 'svc'))
  255. )
  256. ->will($this->onConsecutiveCalls(
  257. // SENTINEL sentinels svc
  258. array(
  259. array(
  260. 'name', '127.0.0.1:5382',
  261. 'ip', '127.0.0.1',
  262. 'port', '5382',
  263. 'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
  264. 'flags', 'sentinel',
  265. ),
  266. ),
  267. // SENTINEL get-master-addr-by-name svc
  268. array('127.0.0.1', '6381'),
  269. // SENTINEL slaves svc
  270. array(
  271. array(
  272. 'name', '127.0.0.1:6382',
  273. 'ip', '127.0.0.1',
  274. 'port', '6382',
  275. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  276. 'flags', 'slave',
  277. 'master-host', '127.0.0.1',
  278. 'master-port', '6381',
  279. ),
  280. array(
  281. 'name', '127.0.0.1:6383',
  282. 'ip', '127.0.0.1',
  283. 'port', '6383',
  284. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  285. 'flags', 'slave',
  286. 'master-host', '127.0.0.1',
  287. 'master-port', '6381',
  288. ),
  289. )
  290. ));
  291. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  292. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  293. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  294. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  295. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  296. $replication->querySentinel();
  297. // TODO: sorry for the smell...
  298. $reflection = new \ReflectionProperty($replication, 'sentinels');
  299. $reflection->setAccessible(true);
  300. $sentinels = array(
  301. array('host' => '127.0.0.1', 'port' => '5381'),
  302. array('host' => '127.0.0.1', 'port' => '5382'),
  303. );
  304. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  305. $this->assertSame($sentinels, array_intersect_key($sentinels, $reflection->getValue($replication)));
  306. $master = $replication->getMaster();
  307. $slaves = $replication->getSlaves();
  308. $this->assertSame('127.0.0.1:6381', (string) $master);
  309. $this->assertCount(2, $slaves);
  310. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  311. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  312. }
  313. /**
  314. * @group disconnected
  315. */
  316. public function testMethodGetMasterAsksSentinelForMasterOnMasterNotSet()
  317. {
  318. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  319. $sentinel1
  320. ->expects($this->at(0))
  321. ->method('executeCommand')
  322. ->with($this->isRedisCommand(
  323. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  324. ))
  325. ->will($this->returnValue(
  326. array('127.0.0.1', '6381')
  327. ));
  328. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  329. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  330. }
  331. /**
  332. * @group disconnected
  333. * @expectedException Predis\ClientException
  334. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  335. */
  336. public function testMethodGetMasterThrowsExceptionOnNoAvailableSentinels()
  337. {
  338. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  339. $sentinel1
  340. ->expects($this->any())
  341. ->method('executeCommand')
  342. ->with($this->isRedisCommand(
  343. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  344. ))
  345. ->will($this->throwException(
  346. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  347. ));
  348. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  349. $replication->getMaster();
  350. }
  351. /**
  352. * @group disconnected
  353. */
  354. public function testMethodGetSlavesOnEmptySlavePoolAsksSentinelForSlaves()
  355. {
  356. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  357. $sentinel1
  358. ->expects($this->at(0))
  359. ->method('executeCommand')
  360. ->with($this->isRedisCommand(
  361. 'SENTINEL', array('slaves', 'svc')
  362. ))
  363. ->will($this->returnValue(
  364. array(
  365. array(
  366. 'name', '127.0.0.1:6382',
  367. 'ip', '127.0.0.1',
  368. 'port', '6382',
  369. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  370. 'flags', 'slave',
  371. 'master-host', '127.0.0.1',
  372. 'master-port', '6381',
  373. ),
  374. array(
  375. 'name', '127.0.0.1:6383',
  376. 'ip', '127.0.0.1',
  377. 'port', '6383',
  378. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  379. 'flags', 'slave',
  380. 'master-host', '127.0.0.1',
  381. 'master-port', '6381',
  382. ),
  383. )
  384. ));
  385. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  386. $slaves = $replication->getSlaves();
  387. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  388. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  389. }
  390. /**
  391. * @group disconnected
  392. * @expectedException Predis\ClientException
  393. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  394. */
  395. public function testMethodGetSlavesThrowsExceptionOnNoAvailableSentinels()
  396. {
  397. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  398. $sentinel1
  399. ->expects($this->any())
  400. ->method('executeCommand')
  401. ->with($this->isRedisCommand(
  402. 'SENTINEL', array('slaves', 'svc')
  403. ))
  404. ->will($this->throwException(
  405. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  406. ));
  407. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  408. $replication->getSlaves();
  409. }
  410. /**
  411. * @group disconnected
  412. * @expectedException Predis\ClientException
  413. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  414. */
  415. public function testMethodConnectThrowsExceptionOnConnectWithEmptySentinelsPool()
  416. {
  417. $replication = $this->getReplicationConnection('svc', array());
  418. $replication->connect();
  419. }
  420. /**
  421. * @group disconnected
  422. */
  423. public function testMethodConnectForcesConnectionToSlave()
  424. {
  425. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  426. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  427. $master
  428. ->expects($this->never())
  429. ->method('connect');
  430. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  431. $slave1
  432. ->expects($this->once())
  433. ->method('connect');
  434. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  435. $replication->add($master);
  436. $replication->add($slave1);
  437. $replication->connect();
  438. }
  439. /**
  440. * @group disconnected
  441. */
  442. public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToSlave()
  443. {
  444. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  445. $sentinel1
  446. ->expects($this->any())
  447. ->method('executeCommand')
  448. ->with($this->isRedisCommand(
  449. 'SENTINEL', array('slaves', 'svc')
  450. ))
  451. ->will($this->returnValue(
  452. array(
  453. array(
  454. 'name', '127.0.0.1:6382',
  455. 'ip', '127.0.0.1',
  456. 'port', '6382',
  457. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  458. 'flags', 'slave',
  459. 'master-host', '127.0.0.1',
  460. 'master-port', '6381',
  461. ),
  462. )
  463. ));
  464. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  465. $master
  466. ->expects($this->never())
  467. ->method('connect');
  468. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  469. $slave1
  470. ->expects($this->once())
  471. ->method('connect');
  472. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  473. $factory
  474. ->expects($this->once())
  475. ->method('create')
  476. ->with(array(
  477. 'host' => '127.0.0.1',
  478. 'port' => '6382',
  479. 'alias' => 'slave-127.0.0.1:6382',
  480. ))
  481. ->will($this->returnValue($slave1));
  482. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  483. $replication->add($master);
  484. $replication->connect();
  485. }
  486. /**
  487. * @group disconnected
  488. */
  489. public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToMasterIfStillEmpty()
  490. {
  491. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  492. $sentinel1
  493. ->expects($this->at(0))
  494. ->method('executeCommand')
  495. ->with($this->isRedisCommand(
  496. 'SENTINEL', array('slaves', 'svc')
  497. ))
  498. ->will($this->returnValue(
  499. array()
  500. ));
  501. $sentinel1
  502. ->expects($this->at(1))
  503. ->method('executeCommand')
  504. ->with($this->isRedisCommand(
  505. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  506. ))
  507. ->will($this->returnValue(
  508. array('127.0.0.1', '6381')
  509. ));
  510. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  511. $master
  512. ->expects($this->once())
  513. ->method('connect');
  514. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  515. $factory
  516. ->expects($this->once())
  517. ->method('create')
  518. ->with(array(
  519. 'host' => '127.0.0.1',
  520. 'port' => '6381',
  521. 'alias' => 'master',
  522. ))
  523. ->will($this->returnValue($master));
  524. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  525. $replication->connect();
  526. }
  527. /**
  528. * @group disconnected
  529. */
  530. public function testMethodDisconnectForcesDisconnectionOnAllConnectionsInPool()
  531. {
  532. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  533. $sentinel1
  534. ->expects($this->never())
  535. ->method('disconnect');
  536. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  537. $master
  538. ->expects($this->once())
  539. ->method('disconnect');
  540. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  541. $slave1
  542. ->expects($this->once())
  543. ->method('disconnect');
  544. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  545. $slave2
  546. ->expects($this->once())
  547. ->method('disconnect');
  548. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  549. $replication->add($master);
  550. $replication->add($slave1);
  551. $replication->add($slave2);
  552. $replication->disconnect();
  553. }
  554. /**
  555. * @group disconnected
  556. */
  557. public function testMethodIsConnectedReturnConnectionStatusOfCurrentConnection()
  558. {
  559. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  560. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  561. $slave1
  562. ->expects($this->exactly(2))
  563. ->method('isConnected')
  564. ->will($this->onConsecutiveCalls(true, false));
  565. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  566. $replication->add($slave1);
  567. $this->assertFalse($replication->isConnected());
  568. $replication->connect();
  569. $this->assertTrue($replication->isConnected());
  570. $replication->getConnectionById('slave1')->disconnect();
  571. $this->assertFalse($replication->isConnected());
  572. }
  573. /**
  574. * @group disconnected
  575. */
  576. public function testMethodGetConnectionByIdReturnsConnectionWhenFound()
  577. {
  578. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  579. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  580. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  581. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  582. $replication->add($master);
  583. $replication->add($slave1);
  584. $this->assertSame($master, $replication->getConnectionById('master'));
  585. $this->assertSame($slave1, $replication->getConnectionById('slave1'));
  586. $this->assertNull($replication->getConnectionById('unknown'));
  587. }
  588. /**
  589. * @group disconnected
  590. */
  591. public function testMethodSwitchToSelectsCurrentConnectionByConnectionAlias()
  592. {
  593. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  594. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  595. $master
  596. ->expects($this->once())
  597. ->method('connect');
  598. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  599. $slave1
  600. ->expects($this->never())
  601. ->method('connect');
  602. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave2');
  603. $slave2
  604. ->expects($this->once())
  605. ->method('connect');
  606. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  607. $replication->add($master);
  608. $replication->add($slave1);
  609. $replication->add($slave2);
  610. $replication->switchTo('master');
  611. $this->assertSame($master, $replication->getCurrent());
  612. $replication->switchTo('slave2');
  613. $this->assertSame($slave2, $replication->getCurrent());
  614. }
  615. /**
  616. * @group disconnected
  617. * @expectedException InvalidArgumentException
  618. * @expectedExceptionMessage Invalid connection or connection not found.
  619. */
  620. public function testMethodSwitchToThrowsExceptionOnConnectionNotFound()
  621. {
  622. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  623. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  624. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  625. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  626. $replication->add($master);
  627. $replication->add($slave1);
  628. $replication->switchTo('unknown');
  629. }
  630. /**
  631. * @group disconnected
  632. */
  633. public function testMethodSwitchToMasterSelectsCurrentConnectionToMaster()
  634. {
  635. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  636. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  637. $master
  638. ->expects($this->once())
  639. ->method('connect');
  640. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  641. $slave1
  642. ->expects($this->never())
  643. ->method('connect');
  644. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  645. $replication->add($master);
  646. $replication->add($slave1);
  647. $replication->switchToMaster();
  648. $this->assertSame($master, $replication->getCurrent());
  649. }
  650. /**
  651. * @group disconnected
  652. */
  653. public function testMethodSwitchToSlaveSelectsCurrentConnectionToRandomSlave()
  654. {
  655. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  656. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  657. $master
  658. ->expects($this->never())
  659. ->method('connect');
  660. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  661. $slave1
  662. ->expects($this->once())
  663. ->method('connect');
  664. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  665. $replication->add($master);
  666. $replication->add($slave1);
  667. $replication->switchToSlave();
  668. $this->assertSame($slave1, $replication->getCurrent());
  669. }
  670. /**
  671. * @group disconnected
  672. */
  673. public function testGetConnectionReturnsMasterForWriteCommands()
  674. {
  675. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  676. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  677. $master
  678. ->expects($this->exactly(2))
  679. ->method('isConnected')
  680. ->will($this->onConsecutiveCalls(false, true));
  681. $master
  682. ->expects($this->at(2))
  683. ->method('executeCommand')
  684. ->with($this->isRedisCommand('ROLE'))
  685. ->will($this->returnValue(array(
  686. 'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
  687. )));
  688. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  689. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  690. $replication->add($master);
  691. $replication->add($slave1);
  692. $this->assertSame($master, $replication->getConnection(
  693. Command\RawCommand::create('set', 'key', 'value')
  694. ));
  695. $this->assertSame($master, $replication->getConnection(
  696. Command\RawCommand::create('del', 'key')
  697. ));
  698. }
  699. /**
  700. * @group disconnected
  701. */
  702. public function testGetConnectionReturnsSlaveForReadOnlyCommands()
  703. {
  704. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  705. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  706. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  707. $slave1
  708. ->expects($this->exactly(2))
  709. ->method('isConnected')
  710. ->will($this->onConsecutiveCalls(false, true));
  711. $slave1
  712. ->expects($this->at(2))
  713. ->method('executeCommand')
  714. ->with($this->isRedisCommand('ROLE'))
  715. ->will($this->returnValue(array(
  716. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  717. )));
  718. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  719. $replication->add($master);
  720. $replication->add($slave1);
  721. $this->assertSame($slave1, $replication->getConnection(
  722. Command\RawCommand::create('get', 'key')
  723. ));
  724. $this->assertSame($slave1, $replication->getConnection(
  725. Command\RawCommand::create('exists', 'key')
  726. ));
  727. }
  728. /**
  729. * @group disconnected
  730. */
  731. public function testGetConnectionSwitchesToMasterAfterWriteCommand()
  732. {
  733. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  734. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  735. $master
  736. ->expects($this->exactly(2))
  737. ->method('isConnected')
  738. ->will($this->onConsecutiveCalls(false, true));
  739. $master
  740. ->expects($this->at(2))
  741. ->method('executeCommand')
  742. ->with($this->isRedisCommand('ROLE'))
  743. ->will($this->returnValue(array(
  744. 'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
  745. )));
  746. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  747. $slave1
  748. ->expects($this->exactly(1))
  749. ->method('isConnected')
  750. ->will($this->onConsecutiveCalls(false));
  751. $slave1
  752. ->expects($this->at(2))
  753. ->method('executeCommand')
  754. ->with($this->isRedisCommand('ROLE'))
  755. ->will($this->returnValue(array(
  756. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  757. )));
  758. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  759. $replication->add($master);
  760. $replication->add($slave1);
  761. $this->assertSame($slave1, $replication->getConnection(
  762. Command\RawCommand::create('exists', 'key')
  763. ));
  764. $this->assertSame($master, $replication->getConnection(
  765. Command\RawCommand::create('set', 'key', 'value')
  766. ));
  767. $this->assertSame($master, $replication->getConnection(
  768. Command\RawCommand::create('get', 'key')
  769. ));
  770. }
  771. /**
  772. * @group disconnected
  773. * @expectedException Predis\Replication\RoleException
  774. * @expectedExceptionMessage Expected master but got slave [127.0.0.1:6381]
  775. */
  776. public function testGetConnectionThrowsExceptionOnNodeRoleMismatch()
  777. {
  778. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  779. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  780. $master
  781. ->expects($this->once())
  782. ->method('isConnected')
  783. ->will($this->returnValue(false));
  784. $master
  785. ->expects($this->at(2))
  786. ->method('executeCommand')
  787. ->with($this->isRedisCommand('ROLE'))
  788. ->will($this->returnValue(array(
  789. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  790. )));
  791. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  792. $replication->add($master);
  793. $replication->getConnection(Command\RawCommand::create('del', 'key'));
  794. }
  795. /**
  796. * @group disconnected
  797. */
  798. public function testGetConnectionReturnsMasterForReadOnlyOperationsOnUnavailableSlaves()
  799. {
  800. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  801. $sentinel1
  802. ->expects($this->once())
  803. ->method('executeCommand')
  804. ->with($this->isRedisCommand(
  805. 'SENTINEL', array('slaves', 'svc')
  806. ))
  807. ->will($this->returnValue(
  808. array(
  809. array(
  810. 'name', '127.0.0.1:6382',
  811. 'ip', '127.0.0.1',
  812. 'port', '6382',
  813. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  814. 'flags', 'slave,s_down,disconnected',
  815. 'master-host', '127.0.0.1',
  816. 'master-port', '6381',
  817. ),
  818. )
  819. ));
  820. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  821. $master
  822. ->expects($this->once())
  823. ->method('isConnected')
  824. ->will($this->returnValue(false));
  825. $master
  826. ->expects($this->at(2))
  827. ->method('executeCommand')
  828. ->with($this->isRedisCommand('ROLE'))
  829. ->will($this->returnValue(array(
  830. 'master', '0', array(),
  831. )));
  832. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  833. $replication->add($master);
  834. $replication->getConnection(Command\RawCommand::create('get', 'key'));
  835. }
  836. /**
  837. * @group disconnected
  838. */
  839. public function testMethodExecuteCommandSendsCommandToNodeAndReturnsResponse()
  840. {
  841. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  842. $cmdGet = Command\RawCommand::create('get', 'key');
  843. $cmdGetResponse = 'value';
  844. $cmdSet = Command\RawCommand::create('set', 'key', 'value');
  845. $cmdSetResponse = Response\Status::get('OK');
  846. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  847. $master
  848. ->expects($this->any())
  849. ->method('isConnected')
  850. ->will($this->returnValue(true));
  851. $master
  852. ->expects($this->at(2))
  853. ->method('executeCommand')
  854. ->with($this->isRedisCommand(
  855. 'SET', array('key', $cmdGetResponse)
  856. ))
  857. ->will($this->returnValue($cmdSetResponse));
  858. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  859. $slave1
  860. ->expects($this->any())
  861. ->method('isConnected')
  862. ->will($this->returnValue(true));
  863. $slave1
  864. ->expects($this->at(2))
  865. ->method('executeCommand')
  866. ->with($this->isRedisCommand(
  867. 'GET', array('key')
  868. ))
  869. ->will($this->returnValue($cmdGetResponse));
  870. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  871. $replication->add($master);
  872. $replication->add($slave1);
  873. $this->assertSame($cmdGetResponse, $replication->executeCommand($cmdGet));
  874. $this->assertSame($cmdSetResponse, $replication->executeCommand($cmdSet));
  875. }
  876. /**
  877. * @group disconnected
  878. */
  879. public function testMethodExecuteCommandRetriesReadOnlyCommandOnNextSlaveOnFailure()
  880. {
  881. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  882. $sentinel1
  883. ->expects($this->any())
  884. ->method('executeCommand')
  885. ->with($this->isRedisCommand(
  886. 'SENTINEL', array('slaves', 'svc')
  887. ))
  888. ->will($this->returnValue(
  889. array(
  890. array(
  891. 'name', '127.0.0.1:6383',
  892. 'ip', '127.0.0.1',
  893. 'port', '6383',
  894. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  895. 'flags', 'slave',
  896. 'master-host', '127.0.0.1',
  897. 'master-port', '6381',
  898. ),
  899. )
  900. ));
  901. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  902. $master
  903. ->expects($this->any())
  904. ->method('isConnected')
  905. ->will($this->returnValue(true));
  906. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  907. $slave1
  908. ->expects($this->any())
  909. ->method('isConnected')
  910. ->will($this->returnValue(true));
  911. $slave1
  912. ->expects($this->at(2))
  913. ->method('executeCommand')
  914. ->with($this->isRedisCommand(
  915. 'GET', array('key')
  916. ))
  917. ->will($this->throwException(
  918. new Connection\ConnectionException($slave1, 'Unknown connection error [127.0.0.1:6382]')
  919. ));
  920. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  921. $slave2
  922. ->expects($this->any())
  923. ->method('isConnected')
  924. ->will($this->returnValue(true));
  925. $slave2
  926. ->expects($this->at(2))
  927. ->method('executeCommand')
  928. ->with($this->isRedisCommand(
  929. 'GET', array('key')
  930. ))
  931. ->will($this->returnValue('value'));
  932. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  933. $factory
  934. ->expects($this->once())
  935. ->method('create')
  936. ->with(array(
  937. 'host' => '127.0.0.1',
  938. 'port' => '6383',
  939. 'alias' => 'slave-127.0.0.1:6383',
  940. ))
  941. ->will($this->returnValue($slave2));
  942. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  943. $replication->add($master);
  944. $replication->add($slave1);
  945. $this->assertSame('value', $replication->executeCommand(
  946. Command\RawCommand::create('get', 'key')
  947. ));
  948. }
  949. /**
  950. * @group disconnected
  951. */
  952. public function testMethodExecuteCommandRetriesWriteCommandOnNewMasterOnFailure()
  953. {
  954. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  955. $sentinel1
  956. ->expects($this->any())
  957. ->method('executeCommand')
  958. ->with($this->isRedisCommand(
  959. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  960. ))
  961. ->will($this->returnValue(
  962. array('127.0.0.1', '6391')
  963. ));
  964. $masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  965. $masterOld
  966. ->expects($this->any())
  967. ->method('isConnected')
  968. ->will($this->returnValue(true));
  969. $masterOld
  970. ->expects($this->at(2))
  971. ->method('executeCommand')
  972. ->with($this->isRedisCommand(
  973. 'DEL', array('key')
  974. ))
  975. ->will($this->throwException(
  976. new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
  977. ));
  978. $masterNew = $this->getMockConnection('tcp://127.0.0.1:6391?alias=master');
  979. $masterNew
  980. ->expects($this->any())
  981. ->method('isConnected')
  982. ->will($this->returnValue(true));
  983. $masterNew
  984. ->expects($this->at(2))
  985. ->method('executeCommand')
  986. ->with($this->isRedisCommand(
  987. 'DEL', array('key')
  988. ))
  989. ->will($this->returnValue(1));
  990. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  991. $factory
  992. ->expects($this->once())
  993. ->method('create')
  994. ->with(array(
  995. 'host' => '127.0.0.1',
  996. 'port' => '6391',
  997. 'alias' => 'master',
  998. ))
  999. ->will($this->returnValue($masterNew));
  1000. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  1001. $replication->add($masterOld);
  1002. $this->assertSame(1, $replication->executeCommand(
  1003. Command\RawCommand::create('del', 'key')
  1004. ));
  1005. }
  1006. /**
  1007. * @group disconnected
  1008. * @expectedException Predis\Response\ServerException
  1009. * @expectedExceptionMessage ERR No such master with that name
  1010. */
  1011. public function testMethodExecuteCommandThrowsExceptionOnUnknownServiceName()
  1012. {
  1013. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  1014. $sentinel1
  1015. ->expects($this->any())
  1016. ->method('executeCommand')
  1017. ->with($this->isRedisCommand(
  1018. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  1019. ))
  1020. ->will($this->returnValue(null));
  1021. $masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  1022. $masterOld
  1023. ->expects($this->any())
  1024. ->method('isConnected')
  1025. ->will($this->returnValue(true));
  1026. $masterOld
  1027. ->expects($this->at(2))
  1028. ->method('executeCommand')
  1029. ->with($this->isRedisCommand(
  1030. 'DEL', array('key')
  1031. ))
  1032. ->will($this->throwException(
  1033. new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
  1034. ));
  1035. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  1036. $replication->add($masterOld);
  1037. $replication->executeCommand(
  1038. Command\RawCommand::create('del', 'key')
  1039. );
  1040. }
  1041. /**
  1042. * @group disconnected
  1043. * @expectedException Predis\ClientException
  1044. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  1045. */
  1046. public function testMethodExecuteCommandThrowsExceptionOnConnectionFailureAndNoAvailableSentinels()
  1047. {
  1048. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  1049. $sentinel1
  1050. ->expects($this->any())
  1051. ->method('executeCommand')
  1052. ->with($this->isRedisCommand(
  1053. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  1054. ))
  1055. ->will($this->throwException(
  1056. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  1057. ));
  1058. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  1059. $master
  1060. ->expects($this->any())
  1061. ->method('isConnected')
  1062. ->will($this->returnValue(true));
  1063. $master
  1064. ->expects($this->at(2))
  1065. ->method('executeCommand')
  1066. ->with($this->isRedisCommand(
  1067. 'DEL', array('key')
  1068. ))
  1069. ->will($this->throwException(
  1070. new Connection\ConnectionException($master, 'Unknown connection error [127.0.0.1:6381]')
  1071. ));
  1072. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  1073. $replication->add($master);
  1074. $replication->executeCommand(
  1075. Command\RawCommand::create('del', 'key')
  1076. );
  1077. }
  1078. /**
  1079. * @group disconnected
  1080. */
  1081. public function testMethodGetReplicationStrategyReturnsInstance()
  1082. {
  1083. $strategy = new Replication\ReplicationStrategy();
  1084. $factory = new Connection\Factory();
  1085. $replication = new SentinelReplication(
  1086. 'svc', array('tcp://127.0.0.1:5381?alias=sentinel1'), $factory, $strategy
  1087. );
  1088. $this->assertSame($strategy, $replication->getReplicationStrategy());
  1089. }
  1090. /**
  1091. * @group disconnected
  1092. */
  1093. public function testMethodSerializeCanSerializeWholeObject()
  1094. {
  1095. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  1096. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  1097. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  1098. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  1099. $strategy = new Replication\ReplicationStrategy();
  1100. $factory = new Connection\Factory();
  1101. $replication = new SentinelReplication('svc', array($sentinel1), $factory, $strategy);
  1102. $replication->add($master);
  1103. $replication->add($slave1);
  1104. $replication->add($slave2);
  1105. $unserialized = unserialize(serialize($replication));
  1106. $this->assertEquals($master, $unserialized->getConnectionById('master'));
  1107. $this->assertEquals($slave1, $unserialized->getConnectionById('slave1'));
  1108. $this->assertEquals($master, $unserialized->getConnectionById('slave2'));
  1109. $this->assertEquals($strategy, $unserialized->getReplicationStrategy());
  1110. }
  1111. // ******************************************************************** //
  1112. // ---- HELPER METHODS ------------------------------------------------ //
  1113. // ******************************************************************** //
  1114. /**
  1115. * Creates a new instance of replication connection.
  1116. *
  1117. * @param string $service Name of the service
  1118. * @param array $sentinels Array of sentinels
  1119. * @param ConnectionFactoryInterface|null $factory Optional connection factory instance.
  1120. *
  1121. * @return SentinelReplication
  1122. */
  1123. protected function getReplicationConnection($service, $sentinels, Connection\FactoryInterface $factory = null)
  1124. {
  1125. $factory = $factory ?: new Connection\Factory();
  1126. $replication = new SentinelReplication($service, $sentinels, $factory);
  1127. $replication->setRetryWait(0);
  1128. return $replication;
  1129. }
  1130. /**
  1131. * Returns a base mocked connection from Predis\Connection\NodeConnectionInterface.
  1132. *
  1133. * @param mixed $parameters Optional parameters.
  1134. *
  1135. * @return mixed
  1136. */
  1137. protected function getMockSentinelConnection($parameters = null)
  1138. {
  1139. $connection = $this->getMockConnection($parameters);
  1140. return $connection;
  1141. }
  1142. }