SentinelReplicationTest.php 47 KB

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