SentinelReplicationTest.php 47 KB

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