1--TEST--
2Causal consistency: second read's afterClusterTime uses last reply's operationTime
3--SKIPIF--
4<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5<?php skip_if_not_libmongoc_crypto(); ?>
6<?php skip_if_not_replica_set_or_mongos_with_replica_set(); ?>
7<?php skip_if_server_version('<', '3.6'); ?>
8<?php skip_if_not_clean(); ?>
9--FILE--
10<?php
11require_once __DIR__ . "/../utils/basic.inc";
12
13class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
14{
15    private $lastSeenOperationTime;
16
17    public function executeReadAfterRead()
18    {
19        $this->lastSeenOperationTime = null;
20
21        MongoDB\Driver\Monitoring\addSubscriber($this);
22
23        $manager = new MongoDB\Driver\Manager(URI);
24        $session = $manager->startSession();
25
26        $query = new MongoDB\Driver\Query([]);
27        $manager->executeQuery(NS, $query, ['session' => $session]);
28        $manager->executeQuery(NS, $query, ['session' => $session]);
29
30        MongoDB\Driver\Monitoring\removeSubscriber($this);
31    }
32
33    public function executeReadAfterWrite()
34    {
35        $this->lastSeenOperationTime = null;
36
37        MongoDB\Driver\Monitoring\addSubscriber($this);
38
39        $manager = new MongoDB\Driver\Manager(URI);
40        $session = $manager->startSession();
41
42        $bulk = new MongoDB\Driver\BulkWrite;
43        $bulk->insert(['x' => 1]);
44        $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
45
46        $query = new MongoDB\Driver\Query([]);
47        $manager->executeQuery(NS, $query, ['session' => $session]);
48
49        MongoDB\Driver\Monitoring\removeSubscriber($this);
50    }
51
52    public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
53    {
54        $command = $event->getCommand();
55        $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
56        printf("%s command includes afterClusterTime: %s\n", $event->getCommandName(), ($hasAfterClusterTime ? 'yes' : 'no'));
57
58        if ($hasAfterClusterTime && $this->lastSeenOperationTime !== null) {
59            printf("%s command uses last seen operationTime: %s\n", $event->getCommandName(), ($command->readConcern->afterClusterTime == $this->lastSeenOperationTime) ? 'yes' : 'no');
60        }
61    }
62
63    public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
64    {
65        $reply = $event->getReply();
66        $hasOperationTime = isset($reply->operationTime);
67
68        printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
69
70        if ($hasOperationTime) {
71            $this->lastSeenOperationTime = $reply->operationTime;
72        }
73    }
74
75    public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
76    {
77    }
78}
79
80echo "Testing read after read\n";
81(new Test)->executeReadAfterRead();
82
83echo "\nTesting read after write\n";
84(new Test)->executeReadAfterWrite();
85
86?>
87===DONE===
88<?php exit(0); ?>
89--EXPECT--
90Testing read after read
91find command includes afterClusterTime: no
92find command reply includes operationTime: yes
93find command includes afterClusterTime: yes
94find command uses last seen operationTime: yes
95find command reply includes operationTime: yes
96
97Testing read after write
98insert command includes afterClusterTime: no
99insert command reply includes operationTime: yes
100find command includes afterClusterTime: yes
101find command uses last seen operationTime: yes
102find command reply includes operationTime: yes
103===DONE===
104