Unverified Commit 27892777 authored by Andreas Braun's avatar Andreas Braun

Merge pull request #671

parents fcd0d78a d353a82f
......@@ -130,7 +130,7 @@ class ListCollections implements Executable
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
}
$cursor = $server->executeCommand($this->databaseName, new Command($cmd), $this->createOptions());
$cursor = $server->executeReadCommand($this->databaseName, new Command($cmd), $this->createOptions());
$cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
return new CollectionInfoCommandIterator(new CachingIterator($cursor));
......
......@@ -98,7 +98,7 @@ class ListDatabases implements Executable
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
}
$cursor = $server->executeCommand('admin', new Command($cmd), $this->createOptions());
$cursor = $server->executeReadCommand('admin', new Command($cmd), $this->createOptions());
$cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
$result = current($cursor->toArray());
......
......@@ -126,7 +126,7 @@ class ListIndexes implements Executable
}
try {
$cursor = $server->executeCommand($this->databaseName, new Command($cmd), $this->createOptions());
$cursor = $server->executeReadCommand($this->databaseName, new Command($cmd), $this->createOptions());
} catch (DriverRuntimeException $e) {
/* The server may return an error if the collection does not exist.
* Check for possible error codes (see: SERVER-20463) and return an
......
......@@ -271,9 +271,15 @@ class MapReduce implements Executable
$command = $this->createCommand($server);
$options = $this->createOptions($hasOutputCollection);
/* If the mapReduce operation results in a write, use
* executeReadWriteCommand to ensure we're handling the writeConcern
* option.
* In other cases, we use executeCommand as this will prevent the
* mapReduce operation from being retried when retryReads is enabled.
* See https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst#unsupported-read-operations. */
$cursor = $hasOutputCollection
? $server->executeReadWriteCommand($this->databaseName, $command, $options)
: $server->executeReadCommand($this->databaseName, $command, $options);
: $server->executeCommand($this->databaseName, $command, $options);
if (isset($this->options['typeMap']) && ! $hasOutputCollection) {
$cursor->setTypeMap(create_field_path_type_map($this->options['typeMap'], 'results.$'));
......
......@@ -77,6 +77,21 @@ class CommandExpectations implements CommandSubscriber
return $o;
}
public static function fromRetryableReads(array $expectedEvents)
{
$o = new self($expectedEvents);
$o->ignoreCommandFailed = true;
$o->ignoreCommandSucceeded = true;
/* Retryable read spec tests don't include extra commands, e.g. the
* killCursors command issued when a change stream is garbage collected.
* We ignore any extra events for that reason. \*/
$o->ignoreExtraEvents = true;
return $o;
}
public static function fromTransactions(array $expectedEvents)
{
$o = new self($expectedEvents);
......
......@@ -21,6 +21,7 @@ use function mt_rand;
*/
final class Context
{
public $bucketName;
public $client;
public $collectionName;
public $databaseName;
......@@ -81,6 +82,19 @@ final class Context
return $o;
}
public static function fromRetryableReads(stdClass $test, $databaseName, $collectionName, $bucketName)
{
$o = new self($databaseName, $collectionName);
$o->bucketName = $bucketName;
$clientOptions = isset($test->clientOptions) ? (array) $test->clientOptions : [];
$o->client = new Client(FunctionalTestCase::getUri(), $clientOptions);
return $o;
}
public static function fromRetryableWrites(stdClass $test, $databaseName, $collectionName)
{
$o = new self($databaseName, $collectionName);
......@@ -133,6 +147,14 @@ final class Context
return $o;
}
/**
* @return Client
*/
public function getClient()
{
return $this->client;
}
public function getCollection(array $collectionOptions = [])
{
return $this->selectCollection(
......@@ -147,6 +169,11 @@ final class Context
return $this->selectDatabase($this->databaseName, $databaseOptions);
}
public function getGridFSBucket(array $bucketOptions = [])
{
return $this->selectGridFSBucket($this->databaseName, $this->bucketName, $bucketOptions);
}
/**
* Prepare options readConcern, readPreference, and writeConcern options by
* creating value objects.
......@@ -272,6 +299,20 @@ final class Context
);
}
public function selectGridFSBucket($databaseName, $bucketName, array $bucketOptions = [])
{
return $this->selectDatabase($databaseName)->selectGridFSBucket($this->prepareGridFSBucketOptions($bucketOptions, $bucketName));
}
private function prepareGridFSBucketOptions(array $options, $bucketPrefix)
{
if ($bucketPrefix !== null) {
$options['bucketPrefix'] = $bucketPrefix;
}
return $options;
}
private function prepareSessionOptions(array $options)
{
if (isset($options['defaultTransactionOptions'])) {
......
......@@ -60,6 +60,17 @@ final class ErrorExpectation
return $o;
}
public static function fromRetryableReads(stdClass $operation)
{
$o = new self();
if (isset($operation->error)) {
$o->isExpected = $operation->error;
}
return $o;
}
public static function fromRetryableWrites(stdClass $outcome)
{
$o = new self();
......
......@@ -185,31 +185,44 @@ class FunctionalTestCase extends BaseFunctionalTestCase
{
$context = $this->getContext();
if ($context->bucketName !== null) {
$bucket = $context->getGridFSBucket($context->defaultWriteOptions);
$bucket->drop();
}
$collection = null;
if ($context->collectionName !== null) {
$collection = $context->getCollection();
$collection->drop($context->defaultWriteOptions);
}
if ($context->outcomeCollectionName !== null) {
$outcomeCollection = $this->getOutcomeCollection();
// Avoid redundant drop if the test and outcome collections are the same
if ($outcomeCollection->getNamespace() !== $collection->getNamespace()) {
if ($collection === null || $outcomeCollection->getNamespace() !== $collection->getNamespace()) {
$outcomeCollection->drop($context->defaultWriteOptions);
}
}
}
/**
* Insert data fixtures into the test collection.
*
* @param array $documents
* @param string|null $collectionName
*/
protected function insertDataFixtures(array $documents)
protected function insertDataFixtures(array $documents, $collectionName = null)
{
if (empty($documents)) {
return;
}
$context = $this->getContext();
$collection = $context->getCollection();
$collection = $collectionName ? $context->selectCollection($context->databaseName, $collectionName) : $context->getCollection();
$collection->insertMany($documents, $context->defaultWriteOptions);
return;
}
private function getOutcomeCollection()
......
This diff is collapsed.
......@@ -89,6 +89,19 @@ final class ResultExpectation
return new self($assertionType, $expectedValue);
}
public static function fromRetryableReads(stdClass $operation, $defaultAssertionType)
{
if (property_exists($operation, 'result') && ! self::isErrorResult($operation->result)) {
$assertionType = $operation->result === null ? self::ASSERT_NULL : $defaultAssertionType;
$expectedValue = $operation->result;
} else {
$assertionType = self::ASSERT_NOTHING;
$expectedValue = null;
}
return new self($assertionType, $expectedValue);
}
public static function fromRetryableWrites(stdClass $outcome, $defaultAssertionType)
{
if (property_exists($outcome, 'result')) {
......
<?php
namespace MongoDB\Tests\SpecTests;
use stdClass;
use function basename;
use function file_get_contents;
use function glob;
use function is_object;
use function strpos;
/**
* Retryable reads spec tests.
*
* @see https://github.com/mongodb/specifications/tree/master/source/retryable-reads
*/
class RetryableReadsSpecTest extends FunctionalTestCase
{
private static $skippedOperations = [
'listCollectionNames' => 'Not implemented',
'listCollectionObjects' => 'Not implemented',
'listDatabaseNames' => 'Not implemented',
'listDatabaseObjects' => 'Not implemented',
'listIndexNames' => 'Not implemented',
];
/**
* Assert that the expected and actual command documents match.
*
* Note: this method may modify the $expected object.
*
* @param stdClass $expected Expected command document
* @param stdClass $actual Actual command document
*/
public static function assertCommandMatches(stdClass $expected, stdClass $actual)
{
static::assertDocumentsMatch($expected, $actual);
}
/**
* Execute an individual test case from the specification.
*
* @dataProvider provideTests
* @param stdClass $test Individual "tests[]" document
* @param array $runOn Top-level "runOn" array with server requirements
* @param array|object $data Top-level "data" array to initialize collection
* @param string $databaseName Name of database under test
* @param string|null $collectionName Name of collection under test
* @param string|null $bucketName Name of GridFS bucket under test
*/
public function testRetryableReads(stdClass $test, array $runOn = null, $data, $databaseName, $collectionName, $bucketName)
{
if (isset($runOn)) {
$this->checkServerRequirements($runOn);
}
foreach (self::$skippedOperations as $operation => $skipReason) {
if (strpos($this->dataDescription(), $operation) === 0) {
$this->markTestSkipped($skipReason);
}
}
if (strpos($this->dataDescription(), 'changeStreams-') === 0) {
$this->skipIfChangeStreamIsNotSupported();
}
$context = Context::fromRetryableReads($test, $databaseName, $collectionName, $bucketName);
$this->setContext($context);
$this->dropTestAndOutcomeCollections();
if (is_object($data)) {
foreach ($data as $collectionName => $documents) {
$this->assertIsArray($documents);
$this->insertDataFixtures($documents, $collectionName);
}
} else {
$this->insertDataFixtures($data);
}
if (isset($test->failPoint)) {
$this->configureFailPoint($test->failPoint);
}
if (isset($test->expectations)) {
$commandExpectations = CommandExpectations::fromRetryableReads($test->expectations);
$commandExpectations->startMonitoring();
}
foreach ($test->operations as $operation) {
Operation::fromRetryableReads($operation)->assert($this, $context);
}
if (isset($commandExpectations)) {
$commandExpectations->stopMonitoring();
$commandExpectations->assert($this, $context);
}
if (isset($test->outcome->collection->data)) {
$this->assertOutcomeCollectionData($test->outcome->collection->data);
}
}
public function provideTests()
{
$testArgs = [];
foreach (glob(__DIR__ . '/retryable-reads/*.json') as $filename) {
$json = $this->decodeJson(file_get_contents($filename));
$group = basename($filename, '.json');
$runOn = isset($json->runOn) ? $json->runOn : null;
$data = isset($json->data) ? $json->data : [];
$databaseName = isset($json->database_name) ? $json->database_name : null;
$collectionName = isset($json->collection_name) ? $json->collection_name : null;
$bucketName = isset($json->bucket_name) ? $json->bucket_name : null;
foreach ($json->tests as $test) {
$name = $group . ': ' . $test->description;
$testArgs[$name] = [$test, $runOn, $data, $databaseName, $collectionName, $bucketName];
}
}
return $testArgs;
}
}
{
"runOn": [
{
"minServerVersion": "4.1.11"
}
],
"database_name": "retryable-reads-tests",
"collection_name": "coll",
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"tests": [
{
"description": "Aggregate with $merge does not retry",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"object": "collection",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
},
{
"$merge": {
"into": "output-collection"
}
}
]
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
},
{
"$merge": {
"into": "output-collection"
}
}
]
},
"command_name": "aggregate",
"database_name": "retryable-reads-tests"
}
}
]
}
]
}
This diff is collapsed.
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"single",
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"database_name": "retryable-reads-tests",
"collection_name": "coll",
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"tests": [
{
"description": "Aggregate succeeds on first attempt",
"operations": [
{
"name": "aggregate",
"object": "collection",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "Aggregate succeeds on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "aggregate",
"object": "collection",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "Aggregate fails on first attempt",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "aggregate",
"object": "collection",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "Aggregate fails on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "aggregate",
"object": "collection",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "Aggregate with $out does not retry",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "aggregate",
"object": "collection",
"arguments": {
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
},
{
"$out": "output-collection"
}
]
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$sort": {
"x": 1
}
},
{
"$out": "output-collection"
}
]
},
"command_name": "aggregate",
"database_name": "retryable-reads-tests"
}
}
]
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"database_name": "retryable-reads-tests",
"collection_name": "coll",
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "client.watch succeeds on first attempt",
"operations": [
{
"name": "watch",
"object": "client"
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
}
]
},
{
"description": "client.watch succeeds on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "client"
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
},
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
}
]
},
{
"description": "client.watch fails on first attempt",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "client",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
}
]
},
{
"description": "client.watch fails on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "client",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
},
{
"command_started_event": {
"command": {
"aggregate": 1,
"cursor": {},
"pipeline": [
{
"$changeStream": {
"allChangesForCluster": true
}
}
]
},
"database_name": "admin"
}
}
]
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"database_name": "retryable-reads-tests",
"collection_name": "coll",
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "db.coll.watch succeeds on first attempt",
"operations": [
{
"name": "watch",
"object": "collection"
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "db.coll.watch succeeds on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "collection"
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "db.coll.watch fails on first attempt",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "db.coll.watch fails on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "watch",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"cursor": {},
"pipeline": [
{
"$changeStream": {}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
}
]
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"single",
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"database_name": "retryable-reads-tests",
"collection_name": "coll",
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "EstimatedDocumentCount succeeds on first attempt",
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"count"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails on first attempt",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"count"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"count"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"count": "coll"
},
"database_name": "retryable-reads-tests"
}
}
]
}
]
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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