PHPLIB-537: "Cursor not found" error is no longer resumable

parent 33fc5e82
...@@ -16,7 +16,6 @@ use MongoDB\Driver\Monitoring\CommandSucceededEvent; ...@@ -16,7 +16,6 @@ use MongoDB\Driver\Monitoring\CommandSucceededEvent;
use MongoDB\Driver\ReadPreference; use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\WriteConcern; use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\ResumeTokenException; use MongoDB\Exception\ResumeTokenException;
use MongoDB\Operation\DatabaseCommand;
use MongoDB\Operation\InsertOne; use MongoDB\Operation\InsertOne;
use MongoDB\Operation\Watch; use MongoDB\Operation\Watch;
use MongoDB\Tests\CommandObserver; use MongoDB\Tests\CommandObserver;
...@@ -224,7 +223,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -224,7 +223,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$postBatchResumeToken = $this->getPostBatchResumeTokenFromReply($events[0]['succeeded']->getReply()); $postBatchResumeToken = $this->getPostBatchResumeTokenFromReply($events[0]['succeeded']->getReply());
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$this->assertNoCommandExecuted(function () use ($changeStream) { $this->assertNoCommandExecuted(function () use ($changeStream) {
$changeStream->rewind(); $changeStream->rewind();
...@@ -303,7 +302,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -303,7 +302,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertInstanceOf(TimestampInterface::class, $operationTime); $this->assertInstanceOf(TimestampInterface::class, $operationTime);
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$this->assertNoCommandExecuted(function () use ($changeStream) { $this->assertNoCommandExecuted(function () use ($changeStream) {
$changeStream->rewind(); $changeStream->rewind();
...@@ -454,7 +453,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -454,7 +453,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertMatchesDocument($expectedResult, $changeStream->current()); $this->assertMatchesDocument($expectedResult, $changeStream->current());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
...@@ -481,10 +480,10 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -481,10 +480,10 @@ class WatchFunctionalTest extends FunctionalTestCase
$operation = new Watch($this->manager, $this->getDatabaseName(), $this->getCollectionName(), [], $this->defaultOptions); $operation = new Watch($this->manager, $this->getDatabaseName(), $this->getCollectionName(), [], $this->defaultOptions);
$changeStream = $operation->execute($this->getPrimaryServer()); $changeStream = $operation->execute($this->getPrimaryServer());
/* Killing the cursor when there are no results will test that neither /* Forcing a resume when there are no results will test that neither
* the initial rewind() nor a resume attempt via next() increment the * the initial rewind() nor a resume attempt via next() increment the
* key. */ * key. */
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$this->assertNoCommandExecuted(function () use ($changeStream) { $this->assertNoCommandExecuted(function () use ($changeStream) {
$changeStream->rewind(); $changeStream->rewind();
...@@ -499,7 +498,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -499,7 +498,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertNull($changeStream->current()); $this->assertNull($changeStream->current());
// A consecutive resume attempt should still not increment the key // A consecutive resume attempt should still not increment the key
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
...@@ -525,10 +524,10 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -525,10 +524,10 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertMatchesDocument($expectedResult, $changeStream->current()); $this->assertMatchesDocument($expectedResult, $changeStream->current());
/* Insert another document and kill the cursor. ChangeStream::next() /* Insert another document and force a resume. ChangeStream::next()
* should resume and pick up the last insert. */ * should resume and pick up the last insert. */
$this->insertDocument(['_id' => 2]); $this->insertDocument(['_id' => 2]);
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertTrue($changeStream->valid()); $this->assertTrue($changeStream->valid());
...@@ -552,7 +551,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -552,7 +551,7 @@ class WatchFunctionalTest extends FunctionalTestCase
* *
* Note: PHPLIB-448 may require rewind() to throw an exception here. */ * Note: PHPLIB-448 may require rewind() to throw an exception here. */
$this->insertDocument(['_id' => 3]); $this->insertDocument(['_id' => 3]);
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$this->assertNoCommandExecuted(function () use ($changeStream) { $this->assertNoCommandExecuted(function () use ($changeStream) {
$changeStream->rewind(); $changeStream->rewind();
...@@ -578,7 +577,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -578,7 +577,7 @@ class WatchFunctionalTest extends FunctionalTestCase
// Test one final, consecutive resume via ChangeStream::next() // Test one final, consecutive resume via ChangeStream::next()
$this->insertDocument(['_id' => 4]); $this->insertDocument(['_id' => 4]);
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertTrue($changeStream->valid()); $this->assertTrue($changeStream->valid());
...@@ -622,7 +621,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -622,7 +621,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
$this->assertNull($changeStream->key()); $this->assertNull($changeStream->key());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertFalse($changeStream->valid()); $this->assertFalse($changeStream->valid());
...@@ -901,7 +900,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -901,7 +900,7 @@ class WatchFunctionalTest extends FunctionalTestCase
]; ];
$this->assertMatchesDocument($expectedResult, $changeStream->current()); $this->assertMatchesDocument($expectedResult, $changeStream->current());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$this->advanceCursorUntilValid($changeStream); $this->advanceCursorUntilValid($changeStream);
$this->assertSame(1, $changeStream->key()); $this->assertSame(1, $changeStream->key());
...@@ -1140,7 +1139,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1140,7 +1139,7 @@ class WatchFunctionalTest extends FunctionalTestCase
); );
$changeStream->rewind(); $changeStream->rewind();
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
(new CommandObserver())->observe( (new CommandObserver())->observe(
function () use (&$changeStream) { function () use (&$changeStream) {
...@@ -1324,7 +1323,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1324,7 +1323,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$changeStream = $operation->execute($secondary); $changeStream = $operation->execute($secondary);
$previousCursorId = $changeStream->getCursorId(); $previousCursorId = $changeStream->getCursorId();
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$changeStream->next(); $changeStream->next();
$this->assertNotSame($previousCursorId, $changeStream->getCursorId()); $this->assertNotSame($previousCursorId, $changeStream->getCursorId());
...@@ -1465,7 +1464,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1465,7 +1464,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$operation = new Watch($this->manager, $this->getDatabaseName(), $this->getCollectionName(), [], $options); $operation = new Watch($this->manager, $this->getDatabaseName(), $this->getCollectionName(), [], $options);
$changeStream = $operation->execute($this->getPrimaryServer()); $changeStream = $operation->execute($this->getPrimaryServer());
$changeStream->rewind(); $changeStream->rewind();
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$aggregateCommand = null; $aggregateCommand = null;
...@@ -1516,7 +1515,7 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1516,7 +1515,7 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->advanceCursorUntilValid($changeStream); $this->advanceCursorUntilValid($changeStream);
$this->assertTrue($changeStream->valid()); $this->assertTrue($changeStream->valid());
$this->killChangeStreamCursor($changeStream); $this->forceChangeStreamResume();
$aggregateCommand = null; $aggregateCommand = null;
...@@ -1552,6 +1551,15 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1552,6 +1551,15 @@ class WatchFunctionalTest extends FunctionalTestCase
$this->assertEmpty($commands); $this->assertEmpty($commands);
} }
private function forceChangeStreamResume(array $commands = ['getMore'], int $errorCode = self::NOT_MASTER)
{
$this->configureFailPoint([
'configureFailPoint' => 'failCommand',
'mode' => ['times' => 1],
'data' => ['failCommands' => $commands, 'errorCode' => $errorCode],
]);
}
private function getPostBatchResumeTokenFromReply(stdClass $reply) private function getPostBatchResumeTokenFromReply(stdClass $reply)
{ {
$this->assertObjectHasAttribute('cursor', $reply); $this->assertObjectHasAttribute('cursor', $reply);
...@@ -1584,17 +1592,6 @@ class WatchFunctionalTest extends FunctionalTestCase ...@@ -1584,17 +1592,6 @@ class WatchFunctionalTest extends FunctionalTestCase
return server_supports_feature($this->getPrimaryServer(), self::$wireVersionForStartAtOperationTime); return server_supports_feature($this->getPrimaryServer(), self::$wireVersionForStartAtOperationTime);
} }
private function killChangeStreamCursor(ChangeStream $changeStream)
{
$command = [
'killCursors' => $this->getCollectionName(),
'cursors' => [ $changeStream->getCursorId() ],
];
$operation = new DatabaseCommand($this->getDatabaseName(), $command);
$operation->execute($this->getPrimaryServer());
}
private function advanceCursorUntilValid(Iterator $iterator, $limitOnShardedClusters = 5) private function advanceCursorUntilValid(Iterator $iterator, $limitOnShardedClusters = 5)
{ {
if (! $this->isShardedCluster()) { if (! $this->isShardedCluster()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment