Skip to content

Commit d901c1a

Browse files
committed
PHPC-986: APM-based tests for retryable writes
PHPC did not require any code changes to support retryable writes, as existing URI option processing allows enabling of retryable writes in libmongoc. These tests utilize APM to assert that certain commands include or exclude a transaction ID.
1 parent a1f694b commit d901c1a

File tree

5 files changed

+416
-0
lines changed

5 files changed

+416
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
--TEST--
2+
Retryable writes: supported single-statement operations include transaction IDs
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
11+
{
12+
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
13+
{
14+
$command = $event->getCommand();
15+
$hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
16+
17+
printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
18+
}
19+
20+
public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
21+
{
22+
}
23+
24+
public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
25+
{
26+
}
27+
}
28+
29+
$observer = new TransactionIdObserver;
30+
MongoDB\Driver\Monitoring\addSubscriber($observer);
31+
32+
$manager = new MongoDB\Driver\Manager(REPLICASET, ['retryWrites' => true]);
33+
34+
echo "Testing deleteOne\n";
35+
$bulk = new MongoDB\Driver\BulkWrite;
36+
$bulk->delete(['x' => 1], ['limit' => 1]);
37+
$manager->executeBulkWrite(NS, $bulk);
38+
39+
echo "\nTesting insertOne\n";
40+
$bulk = new MongoDB\Driver\BulkWrite;
41+
$bulk->insert(['x' => 1]);
42+
$manager->executeBulkWrite(NS, $bulk);
43+
44+
echo "\nTesting replaceOne\n";
45+
$bulk = new MongoDB\Driver\BulkWrite;
46+
$bulk->update(['x' => 1], ['x' => 2]);
47+
$manager->executeBulkWrite(NS, $bulk);
48+
49+
echo "\nTesting updateOne\n";
50+
$bulk = new MongoDB\Driver\BulkWrite;
51+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
52+
$manager->executeBulkWrite(NS, $bulk);
53+
54+
echo "\nTesting findAndModify\n";
55+
$command = new MongoDB\Driver\Command([
56+
'findAndModify' => COLLECTION_NAME,
57+
'query' => ['x' => 1],
58+
'update' => ['$inc' => ['x' => 1]],
59+
]);
60+
$manager->executeReadWriteCommand(DATABASE_NAME, $command);
61+
62+
MongoDB\Driver\Monitoring\removeSubscriber($observer);
63+
64+
?>
65+
===DONE===
66+
<?php exit(0); ?>
67+
--EXPECT--
68+
Testing deleteOne
69+
delete command includes transaction ID: yes
70+
71+
Testing insertOne
72+
insert command includes transaction ID: yes
73+
74+
Testing replaceOne
75+
update command includes transaction ID: yes
76+
77+
Testing updateOne
78+
update command includes transaction ID: yes
79+
80+
Testing findAndModify
81+
findAndModify command includes transaction ID: yes
82+
===DONE===
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
--TEST--
2+
Retryable writes: supported multi-statement operations include transaction IDs
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
11+
{
12+
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
13+
{
14+
$command = $event->getCommand();
15+
$hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
16+
17+
printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
18+
}
19+
20+
public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
21+
{
22+
}
23+
24+
public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
25+
{
26+
}
27+
}
28+
29+
$observer = new TransactionIdObserver;
30+
MongoDB\Driver\Monitoring\addSubscriber($observer);
31+
32+
$manager = new MongoDB\Driver\Manager(REPLICASET, ['retryWrites' => true]);
33+
34+
echo "Testing multi-statement bulk write (ordered=true)\n";
35+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
36+
$bulk->delete(['x' => 1], ['limit' => 1]);
37+
$bulk->insert(['x' => 1]);
38+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
39+
$bulk->update(['x' => 1], ['x' => 2]);
40+
$manager->executeBulkWrite(NS, $bulk);
41+
42+
echo "\nTesting multi-statement bulk write (ordered=false)\n";
43+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
44+
$bulk->delete(['x' => 1], ['limit' => 1]);
45+
$bulk->insert(['x' => 1]);
46+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
47+
$bulk->update(['x' => 1], ['x' => 2]);
48+
$manager->executeBulkWrite(NS, $bulk);
49+
50+
echo "\nTesting insertMany (ordered=true)\n";
51+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
52+
$bulk->insert(['x' => 1]);
53+
$bulk->insert(['x' => 2]);
54+
$manager->executeBulkWrite(NS, $bulk);
55+
56+
echo "\nTesting insertMany (ordered=false)\n";
57+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
58+
$bulk->insert(['x' => 1]);
59+
$bulk->insert(['x' => 2]);
60+
$manager->executeBulkWrite(NS, $bulk);
61+
62+
MongoDB\Driver\Monitoring\removeSubscriber($observer);
63+
64+
?>
65+
===DONE===
66+
<?php exit(0); ?>
67+
--EXPECT--
68+
Testing multi-statement bulk write (ordered=true)
69+
delete command includes transaction ID: yes
70+
insert command includes transaction ID: yes
71+
update command includes transaction ID: yes
72+
73+
Testing multi-statement bulk write (ordered=false)
74+
delete command includes transaction ID: yes
75+
insert command includes transaction ID: yes
76+
update command includes transaction ID: yes
77+
78+
Testing insertMany (ordered=true)
79+
insert command includes transaction ID: yes
80+
81+
Testing insertMany (ordered=false)
82+
insert command includes transaction ID: yes
83+
===DONE===
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
--TEST--
2+
Retryable writes: unsupported operations do not include transaction IDs
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
11+
{
12+
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
13+
{
14+
$command = $event->getCommand();
15+
$hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
16+
17+
printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
18+
}
19+
20+
public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
21+
{
22+
}
23+
24+
public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
25+
{
26+
}
27+
}
28+
29+
$observer = new TransactionIdObserver;
30+
MongoDB\Driver\Monitoring\addSubscriber($observer);
31+
32+
$manager = new MongoDB\Driver\Manager(REPLICASET, ['retryWrites' => true]);
33+
34+
echo "Testing deleteMany\n";
35+
$bulk = new MongoDB\Driver\BulkWrite;
36+
$bulk->delete(['x' => 1], ['limit' => 0]);
37+
$manager->executeBulkWrite(NS, $bulk);
38+
39+
echo "\nTesting updateMany\n";
40+
$bulk = new MongoDB\Driver\BulkWrite;
41+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
42+
$manager->executeBulkWrite(NS, $bulk);
43+
44+
echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=true)\n";
45+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
46+
$bulk->delete(['x' => 1], ['limit' => 1]);
47+
$bulk->insert(['x' => 1]);
48+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
49+
$bulk->update(['x' => 1], ['x' => 2]);
50+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
51+
$manager->executeBulkWrite(NS, $bulk);
52+
53+
echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=false)\n";
54+
$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
55+
$bulk->delete(['x' => 1], ['limit' => 1]);
56+
$bulk->insert(['x' => 1]);
57+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
58+
$bulk->update(['x' => 1], ['x' => 2]);
59+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
60+
$manager->executeBulkWrite(NS, $bulk);
61+
62+
echo "\nTesting aggregate\n";
63+
$command = new MongoDB\Driver\Command([
64+
'aggregate' => COLLECTION_NAME,
65+
'pipeline' => [
66+
['$match' => ['x' => 1]],
67+
['$out' => COLLECTION_NAME . '.out'],
68+
],
69+
'cursor' => new stdClass,
70+
]);
71+
$manager->executeReadWriteCommand(DATABASE_NAME, $command);
72+
73+
MongoDB\Driver\Monitoring\removeSubscriber($observer);
74+
75+
?>
76+
===DONE===
77+
<?php exit(0); ?>
78+
--EXPECT--
79+
Testing deleteMany
80+
delete command includes transaction ID: no
81+
82+
Testing updateMany
83+
update command includes transaction ID: no
84+
85+
Testing multi-statement bulk write with one unsupported operation (ordered=true)
86+
delete command includes transaction ID: yes
87+
insert command includes transaction ID: yes
88+
update command includes transaction ID: no
89+
90+
Testing multi-statement bulk write with one unsupported operation (ordered=false)
91+
delete command includes transaction ID: yes
92+
insert command includes transaction ID: yes
93+
update command includes transaction ID: no
94+
95+
Testing aggregate
96+
aggregate command includes transaction ID: no
97+
===DONE===
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
--TEST--
2+
Retryable writes: unacknowledged write operations do not include transaction IDs
3+
--XFAIL--
4+
Depends on CDRIVER-2432
5+
--SKIPIF--
6+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
7+
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
13+
{
14+
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
15+
{
16+
$command = $event->getCommand();
17+
$hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
18+
19+
printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
20+
}
21+
22+
public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
23+
{
24+
}
25+
26+
public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
27+
{
28+
}
29+
}
30+
31+
$observer = new TransactionIdObserver;
32+
MongoDB\Driver\Monitoring\addSubscriber($observer);
33+
34+
$manager = new MongoDB\Driver\Manager(REPLICASET, ['retryWrites' => true]);
35+
$writeConcern = new MongoDB\Driver\WriteConcern(0);
36+
37+
echo "Testing unacknowledged deleteOne\n";
38+
$bulk = new MongoDB\Driver\BulkWrite;
39+
$bulk->delete(['x' => 1], ['limit' => 1]);
40+
$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
41+
42+
echo "\nTesting unacknowledged insertOne\n";
43+
$bulk = new MongoDB\Driver\BulkWrite;
44+
$bulk->insert(['x' => 1]);
45+
$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
46+
47+
echo "\nTesting unacknowledged replaceOne\n";
48+
$bulk = new MongoDB\Driver\BulkWrite;
49+
$bulk->update(['x' => 1], ['x' => 2]);
50+
$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
51+
52+
echo "\nTesting unacknowledged updateOne\n";
53+
$bulk = new MongoDB\Driver\BulkWrite;
54+
$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
55+
$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
56+
57+
echo "\nTesting unacknowledged findAndModify\n";
58+
$command = new MongoDB\Driver\Command([
59+
'findAndModify' => COLLECTION_NAME,
60+
'query' => ['x' => 1],
61+
'update' => ['$inc' => ['x' => 1]],
62+
'writeConcern' => $writeConcern,
63+
]);
64+
$manager->executeReadWriteCommand(DATABASE_NAME, $command);
65+
66+
MongoDB\Driver\Monitoring\removeSubscriber($observer);
67+
68+
?>
69+
===DONE===
70+
<?php exit(0); ?>
71+
--EXPECT--
72+
Testing unacknowledged deleteOne
73+
delete command includes transaction ID: no
74+
75+
Testing unacknowledged insertOne
76+
insert command includes transaction ID: no
77+
78+
Testing unacknowledged replaceOne
79+
update command includes transaction ID: no
80+
81+
Testing unacknowledged updateOne
82+
update command includes transaction ID: no
83+
84+
Testing unacknowledged findAndModify
85+
findAndModify command includes transaction ID: no
86+
===DONE===

0 commit comments

Comments
 (0)