*Update*: the API proposed below was not what we implemented. See the first linked commit for an overview of the actual API.
Currently we have mongoc_client_command and mongoc_client_command_simple (and equivalents for database and collection). These functions are "generic command methods" and follow driver specs that require they do no special handling of writeConcern, readConcern, or collation. They don't obey the read preference set on the client, database, or collection object. They don't parse writeConcernError from the server reply. This matches various specs that say things like:
The generic command method MUST NOT check the user's command document for a WriteConcern nor check whether the server is new enough to support a write concern for the command. The method simply sends the user's command to the server as-is.
If your driver offers a generic RunCommand method on your database object, ReadConcern MUST NOT be applied automatically to any command. A user wishing to use a ReadConcern in a generic command must supply it manually.
And in the Server Selection Spec:
The generic command method MUST ignore any default read preference from client, database or collection configuration. The generic command method SHOULD allow an optional read preference argument.
HLL drivers built on the C Driver can take advantage of our implementation of driver specs when the HLL drivers call our command-specific helper functions. E.g., when the PHP driver calls mongoc_collection_aggregate_with_opts (
CDRIVER-1526), the C Driver selects a server for the operation, ensures it has a connection, and then applies server version checks for writeConcern, readConcern, and collation ( CDRIVER-1551). It parses the reply for writeConcernError.
Implementing this special logic in the C Driver gives us two benefits: it consolidates logic in the C Driver so it need not be reimplemented in HLL drivers, and it executes the logic after selecting a server and verifying we have an open connection to it, which eliminates all race conditions during server upgrades.
However, to keep taking advantage of these two benefits for all future commands and features, we have to keep adding helper functions with names like mongoc_client_do_new_command_with_opts.
I propose a function that can execute any command, but applies special rules for writeConcern, readConcern, and collation, and all future options with special behavior:
We'll also add equivalents at the database and collection level: mongoc_database_command_with_opts and mongoc_collection_command_with_opts.
Each of these functions:
- Checks the command name and sees if it's a read command like "count"
- Selects a server, applying the client's, database's, or collection's read prefs if this is a read command.
- Ensures a connection to the server.
- Applies or silently omits the writeConcern in "opts", depending on wire version.
- Applies the readConcern in "opts" or returns an error, depending on wire version.
- Applies the collation from "opts" or returns an error depending on wire version.
In the future this will be our "porcelain" command helper for future specs that require special handling of options. mongoc_client_command_simple and other generic command functions remain "plumbing" with no special handling.