Skip to content

Commit f2656f9

Browse files
committed
Fixes
1 parent 0ee577e commit f2656f9

File tree

1 file changed

+62
-21
lines changed

1 file changed

+62
-21
lines changed

src/Client.php

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,10 @@ public function query(array $command, ?string $db = null): stdClass|array|int
286286
// Add transaction options from startTransaction
287287
if (isset($this->sessions[$sessionId]['transactionOptions'])) {
288288
$txnOpts = $this->sessions[$sessionId]['transactionOptions'];
289-
if (isset($txnOpts['readConcern'])) {
289+
if (isset($txnOpts['readConcern']) && !isset($command['readConcern'])) {
290290
$command['readConcern'] = $txnOpts['readConcern'];
291291
}
292-
if (isset($txnOpts['writeConcern'])) {
292+
if (isset($txnOpts['writeConcern']) && !isset($command['writeConcern'])) {
293293
$command['writeConcern'] = $txnOpts['writeConcern'];
294294
}
295295
}
@@ -628,8 +628,8 @@ public function insert(string $collection, array $document, array $options = [])
628628
$command['writeConcern'] = $this->createWriteConcern($options['writeConcern']);
629629
}
630630

631-
// Add read concern if provided with validation
632-
if (isset($options['readConcern'])) {
631+
// Add read concern if provided with validation (skip for non-first transaction operations)
632+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
633633
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
634634
}
635635

@@ -706,8 +706,8 @@ public function insertMany(string $collection, array $documents, array $options
706706
$command['writeConcern'] = $this->createWriteConcern($options['writeConcern']);
707707
}
708708

709-
// Add read concern if provided with validation
710-
if (isset($options['readConcern'])) {
709+
// Add read concern if provided with validation (skip for non-first transaction operations)
710+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
711711
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
712712
}
713713

@@ -787,8 +787,8 @@ public function update(string $collection, array $where = [], array $updates = [
787787
$command['writeConcern'] = $this->createWriteConcern($options['writeConcern']);
788788
}
789789

790-
// Add read concern if provided with validation
791-
if (isset($options['readConcern'])) {
790+
// Add read concern if provided with validation (skip for non-first transaction operations)
791+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
792792
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
793793
}
794794

@@ -875,8 +875,8 @@ public function find(string $collection, array $filters = [], array $options = [
875875
$command['session'] = $options['session'];
876876
}
877877

878-
// Add read concern if provided with validation
879-
if (isset($options['readConcern'])) {
878+
// Add read concern if provided with validation (skip for non-first transaction operations)
879+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
880880
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
881881
}
882882

@@ -924,8 +924,8 @@ public function aggregate(string $collection, array $pipeline, array $options =
924924
$command['session'] = $options['session'];
925925
}
926926

927-
// Add read concern if provided with validation
928-
if (isset($options['readConcern'])) {
927+
// Add read concern if provided with validation (skip for non-first transaction operations)
928+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
929929
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
930930
}
931931

@@ -1032,8 +1032,8 @@ public function delete(string $collection, array $filters = [], int $limit = 1,
10321032
$command['writeConcern'] = $this->createWriteConcern($options['writeConcern']);
10331033
}
10341034

1035-
// Add read concern if provided with validation
1036-
if (isset($options['readConcern'])) {
1035+
// Add read concern if provided with validation (skip for non-first transaction operations)
1036+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
10371037
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
10381038
}
10391039

@@ -1076,8 +1076,8 @@ public function count(string $collection, array $filters, array $options): int
10761076
$command['session'] = $options['session'];
10771077
}
10781078

1079-
// Add read concern if provided with validation
1080-
if (isset($options['readConcern'])) {
1079+
// Add read concern if provided with validation (skip for non-first transaction operations)
1080+
if (isset($options['readConcern']) && !$this->shouldSkipReadConcern($options)) {
10811081
$command['readConcern'] = $this->createReadConcern($options['readConcern']);
10821082
}
10831083

@@ -1196,6 +1196,9 @@ public function startTransaction(array $session, array $options = []): bool
11961196
$sessionState['state'] = self::TRANSACTION_IN_PROGRESS;
11971197
$sessionState['lastUse'] = time();
11981198

1199+
// Reset the firstOperationDone flag for the new transaction
1200+
unset($sessionState['firstOperationDone']);
1201+
11991202
// Store transaction options for use with actual operations
12001203
$sessionState['transactionOptions'] = [];
12011204

@@ -1635,10 +1638,10 @@ public function isTransientTransactionError(Exception $exception): bool
16351638
];
16361639

16371640
return in_array($code, $transientCodes) ||
1638-
str_contains($message, self::TRANSIENT_TRANSACTION_ERROR) ||
1639-
str_contains($message, 'connection') ||
1640-
str_contains($message, 'timeout') ||
1641-
str_contains($message, 'network');
1641+
str_contains($message, self::TRANSIENT_TRANSACTION_ERROR) ||
1642+
str_contains($message, 'connection') ||
1643+
str_contains($message, 'timeout') ||
1644+
str_contains($message, 'network');
16421645
}
16431646

16441647
/**
@@ -1666,7 +1669,7 @@ public function isUnknownTransactionCommitResult(Exception $exception): bool
16661669
];
16671670

16681671
return in_array($code, $unknownCommitCodes) ||
1669-
str_contains($message, self::UNKNOWN_TRANSACTION_COMMIT_RESULT);
1672+
str_contains($message, self::UNKNOWN_TRANSACTION_COMMIT_RESULT);
16701673
}
16711674

16721675
/**
@@ -1875,6 +1878,44 @@ public function createWriteConcern($writeConcern): array
18751878
throw new Exception('Invalid write concern format');
18761879
}
18771880

1881+
/**
1882+
* Check if readConcern should be skipped for a transaction operation
1883+
*
1884+
* @param array $options The options array containing session
1885+
* @return bool True if readConcern should be skipped
1886+
*/
1887+
private function shouldSkipReadConcern(array $options): bool
1888+
{
1889+
if (!isset($options['session'])) {
1890+
return false;
1891+
}
1892+
1893+
$sessionData = $options['session'];
1894+
1895+
// Use the same extraction logic as in query() method
1896+
$sessionId = null;
1897+
if (is_array($sessionData) && isset($sessionData['id'])) {
1898+
$rawId = $sessionData['id']->id ?? null;
1899+
$sessionId = $rawId instanceof \MongoDB\BSON\Binary
1900+
? bin2hex($rawId->getData())
1901+
: $rawId;
1902+
} else {
1903+
$rawId = $sessionData->id ?? null;
1904+
$sessionId = $rawId instanceof \MongoDB\BSON\Binary
1905+
? bin2hex($rawId->getData())
1906+
: $rawId;
1907+
}
1908+
1909+
// If in transaction and not first operation, skip readConcern
1910+
if ($sessionId && isset($this->sessions[$sessionId]) &&
1911+
$this->sessions[$sessionId]['state'] === self::TRANSACTION_IN_PROGRESS &&
1912+
isset($this->sessions[$sessionId]['firstOperationDone'])) {
1913+
return true;
1914+
}
1915+
1916+
return false;
1917+
}
1918+
18781919
/**
18791920
* Create a read concern object with validation.
18801921
*

0 commit comments

Comments
 (0)