Skip to content

Commit 158cc21

Browse files
committed
Merged pull request #551
2 parents 1e2e6b3 + 1f1da78 commit 158cc21

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

tests/DocumentationExamplesTest.php

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace MongoDB\Tests;
44

5+
use MongoDB\Client;
56
use MongoDB\Database;
67
use MongoDB\Driver\Cursor;
78
use MongoDB\Driver\Server;
@@ -1180,6 +1181,245 @@ public function testIndex_example_2()
11801181
$this->assertEquals('cuisine_1_name_1', $indexName);
11811182
}
11821183

1184+
// Start Transactions Intro Example 1
1185+
private function updateEmployeeInfo1(\MongoDB\Client $client, \MongoDB\Driver\Session $session)
1186+
{
1187+
$session->startTransaction([
1188+
'readConcern' => new \MongoDB\Driver\ReadConcern('snapshot'),
1189+
'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY)
1190+
]);
1191+
1192+
try {
1193+
$client->hr->employees->updateOne(
1194+
['employee' => 3],
1195+
['$set' => ['status' => 'Inactive']],
1196+
['session' => $session]
1197+
);
1198+
$client->reporting->events->insertOne(
1199+
['employee' => 3, 'status' => [ 'new' => 'Inactive', 'old' => 'Active']],
1200+
['session' => $session]
1201+
);
1202+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1203+
echo "Caught exception during transaction, aborting.\n";
1204+
$session->abortTransaction();
1205+
throw $error;
1206+
}
1207+
1208+
while (true) {
1209+
try {
1210+
$session->commitTransaction();
1211+
echo "Transaction committed.\n";
1212+
break;
1213+
} catch (\MongoDB\Driver\Exception\CommandException $error) {
1214+
$resultDoc = $error->getResultDocument();
1215+
1216+
if (isset($resultDoc->errorLabels) && in_array('UnknownTransactionCommitResult', $resultDoc->errorLabels)) {
1217+
echo "UnknownTransactionCommitResult, retrying commit operation ...\n";
1218+
continue;
1219+
} else {
1220+
echo "Error during commit ...\n";
1221+
throw $error;
1222+
}
1223+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1224+
echo "Error during commit ...\n";
1225+
throw $error;
1226+
}
1227+
}
1228+
}
1229+
// End Transactions Intro Example 1
1230+
1231+
public function testTransactions_intro_example_1()
1232+
{
1233+
if ($this->getPrimaryServer()->getType() === Server::TYPE_STANDALONE) {
1234+
$this->markTestSkipped('Transactions are not supported on standalone servers');
1235+
}
1236+
if (version_compare($this->getFeatureCompatibilityVersion(), '4.0', '<')) {
1237+
$this->markTestSkipped('Transactions are only supported on FCV 4.0 or higher');
1238+
}
1239+
1240+
$client = new Client($this->getUri());
1241+
1242+
/* The WC is required: https://docs.mongodb.com/manual/core/transactions/#transactions-and-locks */
1243+
$client->hr->dropCollection('employees', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1244+
$client->reporting->dropCollection('events', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1245+
1246+
/* Collections need to be created before a transaction starts */
1247+
$client->hr->createCollection('employees', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1248+
$client->reporting->createCollection('events', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1249+
1250+
$session = $client->startSession();
1251+
1252+
ob_start();
1253+
try {
1254+
$this->updateEmployeeInfo1($client, $session);
1255+
} finally {
1256+
ob_end_clean();
1257+
}
1258+
}
1259+
1260+
// Start Transactions Retry Example 1
1261+
private function runTransactionWithRetry1(callable $txnFunc, \MongoDB\Client $client, \MongoDB\Driver\Session $session)
1262+
{
1263+
while (true) {
1264+
try {
1265+
$txnFunc($client, $session); // performs transaction
1266+
break;
1267+
} catch (\MongoDB\Driver\Exception\CommandException $error) {
1268+
$resultDoc = $error->getResultDocument();
1269+
echo "Transaction aborted. Caught exception during transaction.\n";
1270+
1271+
// If transient error, retry the whole transaction
1272+
if (isset($resultDoc->errorLabels) && in_array('TransientTransactionError', $resultDoc->errorLabels)) {
1273+
echo "TransientTransactionError, retrying transaction ...\n";
1274+
continue;
1275+
} else {
1276+
throw $error;
1277+
}
1278+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1279+
throw $error;
1280+
}
1281+
}
1282+
}
1283+
// End Transactions Retry Example 1
1284+
1285+
// Start Transactions Retry Example 2
1286+
private function commitWithRetry2(\MongoDB\Driver\Session $session)
1287+
{
1288+
while (true) {
1289+
try {
1290+
$session->commitTransaction();
1291+
echo "Transaction committed.\n";
1292+
break;
1293+
} catch (\MongoDB\Driver\Exception\CommandException $error) {
1294+
$resultDoc = $error->getResultDocument();
1295+
1296+
if (isset($resultDoc->errorLabels) && in_array('UnknownTransactionCommitResult', $resultDoc->errorLabels)) {
1297+
echo "UnknownTransactionCommitResult, retrying commit operation ...\n";
1298+
continue;
1299+
} else {
1300+
echo "Error during commit ...\n";
1301+
throw $error;
1302+
}
1303+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1304+
echo "Error during commit ...\n";
1305+
throw $error;
1306+
}
1307+
}
1308+
}
1309+
// End Transactions Retry Example 2
1310+
1311+
// Start Transactions Retry Example 3
1312+
private function runTransactionWithRetry3(callable $txnFunc, \MongoDB\Client $client, \MongoDB\Driver\Session $session)
1313+
{
1314+
while (true) {
1315+
try {
1316+
$txnFunc($client, $session); // performs transaction
1317+
break;
1318+
} catch (\MongoDB\Driver\Exception\CommandException $error) {
1319+
$resultDoc = $error->getResultDocument();
1320+
1321+
// If transient error, retry the whole transaction
1322+
if (isset($resultDoc->errorLabels) && in_array('TransientTransactionError', $resultDoc->errorLabels)) {
1323+
continue;
1324+
} else {
1325+
throw $error;
1326+
}
1327+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1328+
throw $error;
1329+
}
1330+
}
1331+
}
1332+
1333+
private function commitWithRetry3(\MongoDB\Driver\Session $session)
1334+
{
1335+
while (true) {
1336+
try {
1337+
$session->commitTransaction();
1338+
echo "Transaction committed.\n";
1339+
break;
1340+
} catch (\MongoDB\Driver\Exception\CommandException $error) {
1341+
$resultDoc = $error->getResultDocument();
1342+
1343+
if (isset($resultDoc->errorLabels) && in_array('UnknownTransactionCommitResult', $resultDoc->errorLabels)) {
1344+
echo "UnknownTransactionCommitResult, retrying commit operation ...\n";
1345+
continue;
1346+
} else {
1347+
echo "Error during commit ...\n";
1348+
throw $error;
1349+
}
1350+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1351+
echo "Error during commit ...\n";
1352+
throw $error;
1353+
}
1354+
}
1355+
}
1356+
1357+
private function updateEmployeeInfo3(\MongoDB\Client $client, \MongoDB\Driver\Session $session)
1358+
{
1359+
$session->startTransaction([
1360+
'readConcern' => new \MongoDB\Driver\ReadConcern("snapshot"),
1361+
'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY)
1362+
]);
1363+
1364+
try {
1365+
$client->hr->employees->updateOne(
1366+
['employee' => 3],
1367+
['$set' => ['status' => 'Inactive']],
1368+
['session' => $session]
1369+
);
1370+
$client->reporting->events->insertOne(
1371+
['employee' => 3, 'status' => [ 'new' => 'Inactive', 'old' => 'Active']],
1372+
['session' => $session]
1373+
);
1374+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1375+
echo "Caught exception during transaction, aborting.\n";
1376+
$session->abortTransaction();
1377+
throw $error;
1378+
}
1379+
1380+
$this->commitWithRetry3($session);
1381+
}
1382+
1383+
private function doUpdateEmployeeInfo(\MongoDB\Client $client)
1384+
{
1385+
// Start a session.
1386+
$session = $client->startSession();
1387+
1388+
try {
1389+
$this->runTransactionWithRetry3([$this, 'updateEmployeeInfo3'], $client, $session);
1390+
} catch (\MongoDB\Driver\Exception\Exception $error) {
1391+
// Do something with error
1392+
}
1393+
}
1394+
// End Transactions Retry Example 3
1395+
1396+
public function testTransactions_retry_example_3()
1397+
{
1398+
if ($this->getPrimaryServer()->getType() === Server::TYPE_STANDALONE) {
1399+
$this->markTestSkipped('Transactions are not supported on standalone servers');
1400+
}
1401+
if (version_compare($this->getFeatureCompatibilityVersion(), '4.0', '<')) {
1402+
$this->markTestSkipped('Transactions are only supported on FCV 4.0 or higher');
1403+
}
1404+
1405+
$client = new Client($this->getUri());
1406+
1407+
/* The WC is required: https://docs.mongodb.com/manual/core/transactions/#transactions-and-locks */
1408+
$client->hr->dropCollection('employees', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1409+
$client->reporting->dropCollection('events', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1410+
1411+
/* Collections need to be created before a transaction starts */
1412+
$client->hr->createCollection('employees', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1413+
$client->reporting->createCollection('events', ['writeConcern' => new \MongoDB\Driver\WriteConcern('majority')]);
1414+
1415+
ob_start();
1416+
try {
1417+
$this->doUpdateEmployeeInfo($client);
1418+
} finally {
1419+
ob_end_clean();
1420+
}
1421+
}
1422+
11831423
/**
11841424
* Return the test collection name.
11851425
*

0 commit comments

Comments
 (0)