Skip to content

Commit df59e7b

Browse files
committed
Merge pull request #18 from bcrowe/retries
Add optional max retries for collection CRUD operations
2 parents dffa75c + 592e766 commit df59e7b

File tree

2 files changed

+130
-49
lines changed

2 files changed

+130
-49
lines changed

src/League/Monga/Collection.php

+121-49
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ class Collection
2222
*/
2323
protected $collection;
2424

25+
/**
26+
* @var int Amount of times to retry CRUD operations for "not master"
27+
*/
28+
protected $maxRetries = 1;
29+
2530
/**
2631
* Constructor, sets the MongoCollection instance.
2732
*
@@ -56,6 +61,21 @@ public function setCollection(MongoCollection $collection)
5661
return $this;
5762
}
5863

64+
/**
65+
* Set the max amount of times to retry CRUD operations in the case of
66+
* "not master" exceptions.
67+
*
68+
* @param int $amount The amount of times
69+
*
70+
* @return object $this
71+
*/
72+
public function setMaxRetries($amount)
73+
{
74+
$this->maxRetries = $amount;
75+
76+
return $this;
77+
}
78+
5979
/**
6080
* Drops the current collection.
6181
*
@@ -221,18 +241,29 @@ public function remove($criteria, $options = array())
221241
throw new \InvalidArgumentException('Remove criteria must be an array.');
222242
}
223243

224-
try {
225-
$result = $this->collection->remove($criteria, $options);
226-
} catch (MongoCursorException $e) {
227-
// Retry "remove" in case of rediscovery latency issues
228-
// in replica set failover. Error codes 10107, 13435, and 10058
229-
// are MongoCursorException's "not master" errors.
230-
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
244+
$maxRetries = $this->maxRetries;
245+
$tries = 0;
246+
247+
do {
248+
try {
231249
$result = $this->collection->remove($criteria, $options);
232-
} else {
233-
throw $e;
250+
break;
251+
} catch (MongoCursorException $e) {
252+
// Retry "save" in case of rediscovery latency issues
253+
// in replica set failover. Error codes 10107, 13435, and 10058
254+
// are MongoCursorException's "not master" errors.
255+
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
256+
if ($tries === $maxRetries) {
257+
throw $e;
258+
} else {
259+
$tries++;
260+
continue;
261+
}
262+
} else {
263+
throw $e;
264+
}
234265
}
235-
}
266+
} while ($tries <= $maxRetries);
236267

237268
return $result === true || (bool) $result['ok'];
238269
}
@@ -323,21 +354,32 @@ public function findOne($query = array(), $fields = array())
323354
*/
324355
public function insert(array $data, $options = array())
325356
{
357+
$maxRetries = $this->maxRetries;
358+
$tries = 0;
359+
326360
// Check whether we're dealing with a batch insert.
327361
if (isset($data[0]) && is_array($data[0])) {
328362
// Insert using batchInsert
329-
try {
330-
$result = $this->collection->batchInsert($data, $options);
331-
} catch (MongoCursorException $e) {
332-
// Retry "batchInsert" in case of rediscovery latency issues
333-
// in replica set failover. Error codes 10107, 13435, and 10058
334-
// are MongoCursorException's "not master" errors.
335-
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
363+
do {
364+
try {
336365
$result = $this->collection->batchInsert($data, $options);
337-
} else {
338-
throw $e;
366+
break;
367+
} catch (MongoCursorException $e) {
368+
// Retry "save" in case of rediscovery latency issues
369+
// in replica set failover. Error codes 10107, 13435, and 10058
370+
// are MongoCursorException's "not master" errors.
371+
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
372+
if ($tries === $maxRetries) {
373+
throw $e;
374+
} else {
375+
$tries++;
376+
continue;
377+
}
378+
} else {
379+
throw $e;
380+
}
339381
}
340-
}
382+
} while ($tries <= $maxRetries);
341383

342384
if (! $result || ! ($result === true || (bool) $result['ok'])) {
343385
return false;
@@ -354,18 +396,26 @@ public function insert(array $data, $options = array())
354396
return $result;
355397
}
356398

357-
try {
358-
$result = $this->collection->insert($data, $options);
359-
} catch (MongoCursorException $e) {
360-
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
361-
// Retry "insert" in case of rediscovery latency issues
399+
do {
400+
try {
401+
$result = $this->collection->insert($data, $options);
402+
break;
403+
} catch (MongoCursorException $e) {
404+
// Retry "save" in case of rediscovery latency issues
362405
// in replica set failover. Error codes 10107, 13435, and 10058
363406
// are MongoCursorException's "not master" errors.
364-
$result = $this->collection->insert($data, $options);
365-
} else {
366-
throw $e;
407+
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
408+
if ($tries === $maxRetries) {
409+
throw $e;
410+
} else {
411+
$tries++;
412+
continue;
413+
}
414+
} else {
415+
throw $e;
416+
}
367417
}
368-
}
418+
} while ($tries <= $maxRetries);
369419

370420
if ($result === true || (bool) $result['ok']) {
371421
return $data['_id'];
@@ -401,18 +451,29 @@ public function update($values = array(), $query = null, $options = array())
401451

402452
isset($query) || $query = array();
403453

404-
try {
405-
$result = $this->collection->update($query, $values, $options);
406-
} catch (MongoCursorException $e) {
407-
// Retry "update" in case of rediscovery latency issues
408-
// in replica set failover. Error codes 10107, 13435, and 10058
409-
// are MongoCursorException's "not master" errors.
410-
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
454+
$maxRetries = $this->maxRetries;
455+
$tries = 0;
456+
457+
do {
458+
try {
411459
$result = $this->collection->update($query, $values, $options);
412-
} else {
413-
throw $e;
460+
break;
461+
} catch (MongoCursorException $e) {
462+
// Retry "save" in case of rediscovery latency issues
463+
// in replica set failover. Error codes 10107, 13435, and 10058
464+
// are MongoCursorException's "not master" errors.
465+
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
466+
if ($tries === $maxRetries) {
467+
throw $e;
468+
} else {
469+
$tries++;
470+
continue;
471+
}
472+
} else {
473+
throw $e;
474+
}
414475
}
415-
}
476+
} while ($tries <= $maxRetries);
416477

417478
return $result === true || (bool) $result['ok'];
418479
}
@@ -427,18 +488,29 @@ public function update($values = array(), $query = null, $options = array())
427488
*/
428489
public function save(&$document, $options = array())
429490
{
430-
try {
431-
$result = $this->collection->save($document, $options);
432-
} catch (MongoCursorException $e) {
433-
// Retry "save" in case of rediscovery latency issues
434-
// in replica set failover. Error codes 10107, 13435, and 10058
435-
// are MongoCursorException's "not master" errors.
436-
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
491+
$maxRetries = $this->maxRetries;
492+
$tries = 0;
493+
494+
do {
495+
try {
437496
$result = $this->collection->save($document, $options);
438-
} else {
439-
throw $e;
497+
break;
498+
} catch (MongoCursorException $e) {
499+
// Retry "save" in case of rediscovery latency issues
500+
// in replica set failover. Error codes 10107, 13435, and 10058
501+
// are MongoCursorException's "not master" errors.
502+
if (in_array($e->getCode(), array(10107, 13435, 10058))) {
503+
if ($tries === $maxRetries) {
504+
throw $e;
505+
} else {
506+
$tries++;
507+
continue;
508+
}
509+
} else {
510+
throw $e;
511+
}
440512
}
441-
}
513+
} while ($tries <= $maxRetries);
442514

443515
return $result === true || (bool) $result['ok'];
444516
}

tests/CollectionTests.php

+9
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ public function testSetCollection()
5151
$this->collection->setCollection($original);
5252
}
5353

54+
public function testSetMaxRetries()
55+
{
56+
$this->collection->setMaxRetries(5);
57+
$reflection = new ReflectionObject($this->collection);
58+
$property = $reflection->getProperty('maxRetries');
59+
$property->setAccessible(true);
60+
$this->assertEquals(5, $property->getValue($this->collection));
61+
}
62+
5463
public function testCount()
5564
{
5665
$result = $this->collection->count();

0 commit comments

Comments
 (0)