Skip to content

Commit

Permalink
Extend handling to include if a write was retried
Browse files Browse the repository at this point in the history
  • Loading branch information
thekid committed Oct 12, 2024
1 parent 826c59d commit 113a601
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 7 deletions.
9 changes: 7 additions & 2 deletions src/main/php/com/mongodb/Error.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ public function __construct($code, $kind, $message, $cause= null) {
* Creates an error from a given error document
*
* @param [:var] $document
* @param int|bool $retried
* @return self
*/
public static function newInstance($document) {
return new self($document['code'], $document['codeName'], $document['errmsg']);
public static function newInstance($document, $retried= 0) {
return new self(
$document['code'],
$document['codeName'],
$document['errmsg'].($retried ? " - retried {$retried} time(s)" : '')
);
}

/** @return string */
Expand Down
2 changes: 1 addition & 1 deletion src/main/php/com/mongodb/io/Commands.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function send($options, $sections) {
goto retry;
}

throw Error::newInstance($r['body']);
throw Error::newInstance($r['body'], !$this->retry);
} finally {
$this->retry= false;
}
Expand Down
7 changes: 4 additions & 3 deletions src/main/php/com/mongodb/io/Protocol.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public function write(array $options, $sections) {
}

$rp= $sections['$readPreference'] ?? $this->readPreference;
$retry= 1;
$retry= true;

// Use send() API to prevent using exceptions for flow control
retry: $conn= $this->establish([$this->nodes['primary']], 'writing');
Expand All @@ -271,12 +271,13 @@ public function write(array $options, $sections) {
// Check for "NotWritablePrimary" error, which indicates our view of the cluster
// may be outdated, see https://github.com/xp-forge/mongodb/issues/43. Refresh
// view using the "hello" command, then retry the command once.
if ($retry-- && isset(Error::NOT_PRIMARY[$r['body']['code']])) {
if ($retry && isset(Error::NOT_PRIMARY[$r['body']['code']])) {
$this->useCluster($conn->hello());
$retry= false;
goto retry;
}

throw Error::newInstance($r['body']);
throw Error::newInstance($r['body'], !$retry);
}

/** @return void */
Expand Down
10 changes: 9 additions & 1 deletion src/test/php/com/mongodb/unittest/CollectionTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -406,12 +406,20 @@ public function not_writable_primary_retried($kind, $command) {
));
}

#[Test, Expect(class: Error::class, message: 'Second occurrence'), Values(from: 'writes')]
#[Test, Expect(class: Error::class, message: 'Second occurrence - retried 1 time(s)'), Values(from: 'writes')]
public function not_writable_primary_not_retried_more_than_once($kind, $command) {
$command($this->newFixture(
$this->error(10107, 'NotWritablePrimary', 'First occurrence'),
$this->hello(self::$PRIMARY),
$this->error(10107, 'NotWritablePrimary', 'Second occurrence')
));
}

#[Test, Expect(class: Error::class, message: 'Test message'), Values(from: 'writes')]
public function other_errors_not_retried($kind, $command) {
$command($this->newFixture(
$this->error(6100, 'FailedOnce', 'Test message'),
$this->error(6101, 'FailedAgain', 'The previous error should have thrown')
));
}
}

0 comments on commit 113a601

Please sign in to comment.