Status: | Accepted |
---|---|
Minimum Server Version: | N/A |
As MongoDB moves toward more frequent releases (a.k.a. continuous delivery), we want to enable users to take advantage of our rapidly released features, without exposing applications to incompatible server changes due to automatic server upgrades. A stable API will help accomplish that goal.
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
This document tends to use "SHOULD" more frequently than other specifications, but mainly in the context of providing guidance on writing test files. This is discussed in more detail in Design Rationale.
When applications interact with MongoDB, both the driver and the server participate in executing operations. Therefore, when determining application compatibility with MongoDB, both the driver and the server behavior must be taken into account.
An application can specify the server API version when creating MongoClient. When this is done:
- The client sends the specified API version to the server, causing the server to behave in a manner compatible with that API version.
- The driver will behave in a manner compatible with a server configured with that API version, regardless of the server's actual release version.
Presently there is no specification for how a driver must behave when a particular server API version is requested, or what driver operations are subject to API compatibility guarantees. Such requirements may be stipulated in subsequent specifications.
This specification requires MongoClient to validate that it supports the specified server API version, if any, but does not define what such support means.
MongoClient
instances accept a new serverApi
option to allow the user to
declare an API version:
class MongoClient {
MongoClient(... serverApi: ServerApi);
}
enum ServerApiVersion {
v1 = "1",
}
class ServerApi {
version: string|ServerApiVersion;
strict: Optional<Boolean>; // Default false
deprecationErrors: Optional<Boolean>; // Default false
}
Drivers SHOULD group the serverApi
option with other similar client options
like autoEncryptionOpts
. Drivers MUST NOT allow specification of any
stable API options via the connection string. See the
Design Rationale for more details.
This specification and subsequent specifications will define the known API
versions. Drivers SHOULD define an enumeration containing the known API
versions, using the version identifiers given. Drivers MAY deviate from the
version identifiers used in this and subsequent specifications if doing so is
necessary given the driver's programming language's constraints. Drivers MUST
ensure that adding new API versions to this enumeration does not result in
backward compatibility breaks in non-major releases. This can be the case in
languages that allow exhaustive switch
statements (e.g. Swift).
Drivers for languages that don't have enums (e.g. PHP) MUST expose the version
as a string, but SHOULD offer constants to allow for IDE features such as code
completion. In these cases, the driver MUST validate (e.g. when the application
provides a version string to the ServerApi
class) that the version string is
valid and trigger a client-side error if an unknown API version was used.
The ServerApi
class stores an API version, along with flags that decide
whether or not unknown or deprecated commands in the specified API version
trigger a server-side error. A version
MUST be specified when declaring an
API version, while the strict
and deprecationErrors
options are both
optional. The ServerApi
class is considered immutable; changes to the
declared API version MUST be prohibited.
Drivers MUST ensure that users cannot override the API version declared in the
MongoClient
instance. This includes the MongoDatabase
and
MongoCollection
classes, as well as any operations in these classes. See the
rationale for more details.
The declared API version MUST be sent to the server as part of every command
request, with the exception of the cases listed below. Drivers MUST NOT use a
server's reported maxWireVersion
to decide whether it supports the stable
API. The server will reply with an error if the declared API version is not
supported, or if the command does not support API versioning options. If the
user does not declare an API version, the driver MUST NOT send any API
versioning options to the server.
If an API version is declared then the driver MUST use
OP_MSG
for all messages, including the initial handshake.
The options from the declared API version are mapped to the following command options:
ServerApi field | Command option |
version |
apiVersion |
strict |
apiStrict |
deprecationErrors |
apiDeprecationErrors |
If an API version was declared, drivers MUST add the apiVersion
option to
every command that is sent to a server. Drivers MUST add the apiStrict
and
apiDeprecationErrors
options if they were specified by the user, even when
the specified value is equal to the server default. Drivers MUST NOT add any
API versioning options if the user did not specify them.
This includes the getMore
command as well as all commands that are part of a
transaction. A previous version of this specification excluded those commands,
but that has since changed in the server.
If an API version was declared, drivers MUST NOT use the legacy hello command
during the initial handshake or afterwards. Instead, drivers MUST use the
hello
command exclusively and use the OP_MSG
protocol.
If the server does not support hello
, the server description MUST
reflect this with an Unknown
server type.
For getMore
, drivers MUST submit API parameters. If the values given do not
match the API parameters given in the cursor-initiating command, the server will
reply with an error.
When running commands as part of a transaction, drivers MUST send API
parameters with all commands that are part of a transaction, including
commitTransaction
and abortTransaction
. If the API parameters for a
command in a transaction do not match those of the transaction-starting command,
the server will reply with an error.
Drivers that offer a generic command helper (e.g. command()
or
runCommand()
) MUST NOT inspect the command document to detect API versioning
options. As with all other commands, drivers MUST inherit the API version from
the client. Specifying API versioning options in the command document and
declaring an API version on the client is not supported. Drivers MUST document
that the behaviour of the command helper is undefined in this case.
Since changing the API version can cause the application to behave differently, drivers MUST NOT allow users to change the declared API version without deploying code changes. This ensures that users don't copy a connection string with a declared API version that may be different from what their application expects. A URI option can be added later if we realise our users need it, while the opposite is not easily accomplished.
While users are used to overriding options like read preference, read concern,
and write concern in MongoDatabase
and MongoCollection
objects, or on an
operation level, we explicitly decided against this for the declared API
version. With a single API version available to start, we can't anticipate what
use cases users may have to override the API version. Not including this feature
at the beginning allows us to gather feedback on use cases and add the features
users are looking for. On the other hand, adding the ability to override the
declared API version can't be undone until a future major release, which is
almost impossible to accomplish across all drivers.
The runCommand helper is a way for the user to run a native command with the
driver doing little to no inspection in the command. This allows users to run
arbitrary commands that may not have helpers in the driver, or to pass options
that are not supported by the driver version they are currently using. Commands
run using this helper do not inherit any readConcern
or writeConcern
options that may have been set on the MongoClient
or MongoDatabase
objects.
However, the declared API version is a different case. We are introducing this feature to give users a certain peace of mind when upgrading driver or server versions, by ensuring that their code will continue to show the same behaviour they've gotten used to. This includes all commands run using the generic command helper. Thus, the helper will inherit the API version declared on the client.
Since a new API version might require driver changes (e.g. to account for removed commands), we don't yet know what changes drivers must make for a future version. Until we do, we must prevent users from choosing any unknown API version.
Driver changes are fully backward compatible. Not declaring an API version when
creating a client may cause an error if the server was started with the
requireApiVersion
option enabled, but this is outside of driver control.
In the future, we may want to allow users to override the declared API version
on a MongoDatabase
, MongoCollection
, or individual operation level.
However, this is not necessary until there is a different API version and we
have data on why and how users would want to override the declared API version.
Drivers may also want to provide specialized MongoClient
, MongoDatabase
,
and MongoCollection
classes to only include features that are part of the
stable API. This is not covered in this specification.
2022-10-05: | Remove spec front matter and reformat changelog. |
---|---|
2022-02-24: | Rename Versioned API to Stable API |
2022-01-14: | Require OP_MSG for all messages including the initial step of
the handshake when using stable API. |
2021-05-05: | Require sending stable API parameters with getMore and
transaction-continuing commands. |
2021-04-20: | Require using hello when using the stable API. |
2021-04-10: | Replaced usages of acceptAPIVersion2 with acceptApiVersion2 . |