From 622cd6b86e07eb00092a0d92ea84e630b7058c31 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 13:39:42 +0300 Subject: [PATCH 1/4] Update readConcern handling for unsupported commands --- src/Client.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Client.php b/src/Client.php index c6d2c91..72df20a 100644 --- a/src/Client.php +++ b/src/Client.php @@ -66,7 +66,7 @@ class Client public const COMMAND_END_SESSIONS = "endSessions"; public const COMMAND_LIST_INDEXES = "listIndexes"; public const COMMAND_COLLMOD = "collMod"; - + public const COMMAND_KILL_CURSORS = "killCursors"; // Connection and performance settings private int $defaultMaxTimeMS = 30000; // 30 seconds default @@ -97,6 +97,14 @@ class Client public const READ_PREFERENCE_SECONDARY_PREFERRED = 'secondaryPreferred'; public const READ_PREFERENCE_NEAREST = 'nearest'; + /** + * Commands that don't support readConcern + */ + private array $readConcernNotSupporteedCommands = [ + self::COMMAND_GET_MORE, + self::COMMAND_KILL_CURSORS + ]; + /** * Authentication for connection @@ -320,7 +328,10 @@ public function query(array $command, ?string $db = null): stdClass|array|int // CRITICAL: Remove readConcern from any non-first operation in a transaction // MongoDB will reject commands with readConcern that have txnNumber but not startTransaction - if (isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) { + // Or if the command is in the readConcernNotSupporteedCommands array + if (((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) + || + in_array(array_keys($command)[0] ?? '', $this->readConcernNotSupporteedCommands))) { unset($command['readConcern']); } @@ -2051,4 +2062,4 @@ public function __destruct() { $this->close(); } -} +} \ No newline at end of file From 62d03aebb653e3b4f05538c48fb4cabaa27f5cb8 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 13:40:14 +0300 Subject: [PATCH 2/4] linter --- src/Client.php | 6 +++--- tests/TransactionTest.php | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Client.php b/src/Client.php index 72df20a..7a20dfd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -101,7 +101,7 @@ class Client * Commands that don't support readConcern */ private array $readConcernNotSupporteedCommands = [ - self::COMMAND_GET_MORE, + self::COMMAND_GET_MORE, self::COMMAND_KILL_CURSORS ]; @@ -330,7 +330,7 @@ public function query(array $command, ?string $db = null): stdClass|array|int // MongoDB will reject commands with readConcern that have txnNumber but not startTransaction // Or if the command is in the readConcernNotSupporteedCommands array if (((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) - || + || in_array(array_keys($command)[0] ?? '', $this->readConcernNotSupporteedCommands))) { unset($command['readConcern']); } @@ -2062,4 +2062,4 @@ public function __destruct() { $this->close(); } -} \ No newline at end of file +} diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 1ae7643..b4cb651 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -162,7 +162,6 @@ public function testTransactionStateManagement() // Verify final state $finalState = $client->getSessionState($session); $this->assertEquals('committed', $finalState['state']); - } finally { $client->endSessions([$session]); } @@ -202,7 +201,6 @@ public function testTransactionAbort() // Verify document was not inserted (transaction rolled back) $found = $client->find('test_collection', ['name' => 'abort_test']); $this->assertEmpty($found->cursor->firstBatch); - } finally { $client->endSessions([$session]); } @@ -251,7 +249,6 @@ public function testWithTransactionHelper() $this->assertNotEmpty($found1->cursor->firstBatch); $this->assertNotEmpty($found2->cursor->firstBatch); - } finally { $client->endSessions([$session]); } @@ -343,7 +340,6 @@ public function testCRUDWithSessionAndConcerns() $this->assertEquals(1, $count); $client->commitTransaction($session); - } finally { $client->endSessions([$session]); } From ce62464142489a71b37da47720a0e66be0ae2ac8 Mon Sep 17 00:00:00 2001 From: Shimon Newman Date: Mon, 20 Oct 2025 13:59:40 +0300 Subject: [PATCH 3/4] Update src/Client.php Co-authored-by: Jake Barnby --- src/Client.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Client.php b/src/Client.php index 7a20dfd..1d54284 100644 --- a/src/Client.php +++ b/src/Client.php @@ -330,8 +330,10 @@ public function query(array $command, ?string $db = null): stdClass|array|int // MongoDB will reject commands with readConcern that have txnNumber but not startTransaction // Or if the command is in the readConcernNotSupporteedCommands array if (((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) - || - in_array(array_keys($command)[0] ?? '', $this->readConcernNotSupporteedCommands))) { + if ( + ((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) + || \in_array(array_key_first($command) ?? '', $this->readConcernNotSupporteedCommands)) + ) { unset($command['readConcern']); } From 5206ea94f69b434a2ca0b09abd668fd1b6f18969 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 14:04:34 +0300 Subject: [PATCH 4/4] linter and typo fix --- src/Client.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Client.php b/src/Client.php index 1d54284..93ea8ab 100644 --- a/src/Client.php +++ b/src/Client.php @@ -98,9 +98,9 @@ class Client public const READ_PREFERENCE_NEAREST = 'nearest'; /** - * Commands that don't support readConcern + * Commands that do not support readConcern options */ - private array $readConcernNotSupporteedCommands = [ + private array $readConcernNotSupportedCommands = [ self::COMMAND_GET_MORE, self::COMMAND_KILL_CURSORS ]; @@ -328,11 +328,14 @@ public function query(array $command, ?string $db = null): stdClass|array|int // CRITICAL: Remove readConcern from any non-first operation in a transaction // MongoDB will reject commands with readConcern that have txnNumber but not startTransaction - // Or if the command is in the readConcernNotSupporteedCommands array - if (((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) + // Or if the command is in the readConcernNotSupportedCommands array if ( - ((isset($command['txnNumber']) && !isset($command['startTransaction']) && isset($command['readConcern'])) - || \in_array(array_key_first($command) ?? '', $this->readConcernNotSupporteedCommands)) + ( + isset($command['txnNumber']) + && !isset($command['startTransaction']) + && isset($command['readConcern']) + ) + || \in_array(array_key_first($command) ?? '', $this->readConcernNotSupportedCommands) ) { unset($command['readConcern']); }