Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHPLIB-476: Consider transaction readPreference in select_server #1178

Merged
merged 2 commits into from
Oct 4, 2023

Conversation

jmikola
Copy link
Member

@jmikola jmikola commented Sep 26, 2023

https://jira.mongodb.org/browse/PHPLIB-476

This also refactors the conditionals in extract_session_from_options and extract_read_preference_from_options to improve readability.

select_server() previously did not consider the read preference of an active transaction. This isn't very significant, as transactions require a primary read preference, but it is correct to do so.

@jmikola jmikola requested review from alcaeus and GromNaN September 26, 2023 19:03
}

// Manager::selectServer() defaults to a primary read preference
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since 1.11 (PHPC-1937).


$this->assertTrue($session->isInTransaction());
$this->assertInstanceOf(Server::class, $session->getServer(), 'Session is pinned');
$this->assertEquals($session->getServer(), select_server($client->getManager(), ['session' => $session]));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this test is still a bit dubious, as we don't have any insight into what Manager::selectServer() is actually doing. That may change with server selection logging (PHPLIB-1000).

Currently, there's a chance that server selection just happens to select the same server that was pinned (see: Topology type: Sharded in the Server Selection spec). Supplying an alternative read preference in the operation-level options doesn't really affect this, since it wouldn't influence mongos selection. Again, logging would help verify that.

Having said all that, I think adding a functional test is a good first step since we previously had no direct test coverage for this function. This file at least provides a starting point to add more coverage down the line. I've left a comment in PHPLIB-1000 to that effect.

Copy link
Member

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, suggested a change to work around the Psalm error.

src/functions.php Outdated Show resolved Hide resolved
@jmikola jmikola force-pushed the phplib-476 branch 2 times, most recently from 0459bc2 to 7262c64 Compare September 28, 2023 16:31
This also refactors the conditionals in extract_session_from_options and extract_read_preference_from_options to improve readability.

select_server() previously did not consider the read preference of an active transaction. This isn't very significant, as transactions require a primary read preference, but it is correct to do so.
*
* @internal
*/
function select_server_for_write(Manager $manager, array $options): Server
Copy link
Member Author

@jmikola jmikola Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting Transactions: readPreference:

The read preference to use for all read operations in this transaction.

The select_server_for_write() method here allows us to avoid considering a transaction's readPreference option for a known write command. I intentionally chose not to use this method for read methods that are typically run on primaries (e.g. collection and database enumeration). And it's not used for Database::command() sinec that's considered a read operation (see: runCommand spec).

It's clear we don't have comprehensive test coverage for this across all operations (for example, there's no test that tries to list databases within a transaction), but I'm glad that I was alerted to this oversight in some failing legacy transaction spec tests.

@jmikola
Copy link
Member Author

jmikola commented Oct 2, 2023

Test failures seem to be due to an unrelated change in drivers-evergreen-tools, which I'm tracking in https://github.com/mongodb-labs/drivers-evergreen-tools/pull/352/files#r1342969157. I'll wait for that to get resolved before moving forward with this PR.

@jmikola jmikola requested review from alcaeus and GromNaN October 3, 2023 13:07
Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
I let you decide for search index operations.

@@ -418,7 +418,7 @@ public function createSearchIndex($definition, array $options = []): string
public function createSearchIndexes(array $indexes, array $options = []): array
{
$operation = new CreateSearchIndexes($this->databaseName, $this->collectionName, $indexes, $options);
$server = select_server($this->manager, $options);
$server = select_server_for_write($this->manager, $options);
Copy link
Member

@GromNaN GromNaN Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if that's relevant for search indexes.

These commands internally proxy the search index management commands to a separate process that runs alongside an Atlas cluster. As such, read concern and write concern are not relevant for the search index management commands.
https://github.com/mongodb/specifications/blob/db3114e957f7c0976a1af09882dbb46cb4a70049/source/index-management/index-management.rst#where-are-read-concern-and-write-concern

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm familiar with mongot, but does that mean mongod has absolutely not state when it comes to search indexes? Perhaps that's the case, as listSearchIndexes() is distinct from listIndexes().

This also raises the question of what happens if the search index operations are executed within a transaction. Presumably they don't maintain state on mongod at all (and thus operate outside of a transaction), but it's not clear to me if mongod would actually restrict their usage during an active transaction.

That said, I don't see the harm in requiring a primary in this case since it is a write operation from the user's perspective.

@jmikola jmikola merged commit f32542d into mongodb:master Oct 4, 2023
12 checks passed
@jmikola jmikola deleted the phplib-476 branch October 4, 2023 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants