Skip to content

Commit 7e1d680

Browse files
authored
RUST-649 Document versioned API usage with examples (#316)
1 parent d1a7719 commit 7e1d680

File tree

3 files changed

+80
-8
lines changed

3 files changed

+80
-8
lines changed

src/client/options/mod.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -248,19 +248,22 @@ impl<'de> Deserialize<'de> for ServerApiVersion {
248248
}
249249
}
250250

251-
/// Declares a versioned server API
251+
/// Options used to declare a versioned server API.
252252
#[derive(Clone, Debug, Deserialize, PartialEq, TypedBuilder)]
253253
#[serde(rename_all = "camelCase")]
254254
#[non_exhaustive]
255255
pub(crate) struct ServerApi {
256-
/// The version string of the declared API version
256+
/// The declared API version.
257257
pub version: ServerApiVersion,
258258

259-
/// Whether the server should return errors for features that are not part of the API version
259+
/// Whether the MongoDB server should reject all commands that are not part of the
260+
/// declared API version. This includes command options and aggregation pipeline stages.
260261
#[builder(default)]
261262
pub strict: Option<bool>,
262263

263-
/// Whether the server should return errors for deprecated features
264+
/// Whether the MongoDB server should return command failures when functionality that is
265+
/// deprecated from the declared API version is used.
266+
/// Note that at the time of this writing, no deprecations in version 1 exist.
264267
#[builder(default)]
265268
pub deprecation_errors: Option<bool>,
266269
}
@@ -400,9 +403,15 @@ pub struct ClientOptions {
400403
#[builder(default)]
401404
pub selection_criteria: Option<SelectionCriteria>,
402405

403-
/// The declared API version
406+
/// The declared API version for this client.
407+
/// The declared API version is applied to all commands run through the client, including those
408+
/// sent through any [crate::Database] or [crate::Collection] derived from the client.
404409
///
405-
/// The default value is to have no declared API version
410+
/// Specifying versioned API options in the command document passed to
411+
/// [crate::Database::run_command] AND declaring an API version on the client is not
412+
/// supported and is considered undefined behaviour. To run any command with a different API
413+
/// version or without declaring one, create a separate client that declares the
414+
/// appropriate API version.
406415
#[builder(default, skip)]
407416
pub(crate) server_api: Option<ServerApi>,
408417

src/test/documentation_examples.rs

+64-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use futures::TryStreamExt;
2+
use tokio::sync::RwLockReadGuard;
23

34
use crate::{
45
bson::{doc, Bson},
56
error::Result,
6-
options::FindOptions,
7-
test::TestClient,
7+
options::{ClientOptions, CursorType, FindOptions, ServerApi, ServerApiVersion},
8+
test::{TestClient, DEFAULT_URI, LOCK},
9+
Client,
810
Collection,
911
};
1012

@@ -1364,9 +1366,68 @@ async fn delete_examples(collection: &Collection) -> Result<()> {
13641366
Ok(())
13651367
}
13661368

1369+
#[allow(unused_variables)]
1370+
#[cfg(not(feature = "sync"))]
1371+
async fn versioned_api_examples() -> Result<()> {
1372+
let setup_client = TestClient::new().await;
1373+
if setup_client.server_version_lt(4, 9) {
1374+
println!("skipping versioned API examples due to unsupported server version");
1375+
return Ok(());
1376+
}
1377+
1378+
let uri = DEFAULT_URI.clone();
1379+
// Start 1. Declare an API version on a client
1380+
let mut options = ClientOptions::parse(&uri).await?;
1381+
let server_api = ServerApi::builder()
1382+
.version(ServerApiVersion::Version1)
1383+
.build();
1384+
options.server_api = Some(server_api);
1385+
let client = Client::with_options(options)?;
1386+
let cursor = client
1387+
.database("versioned_api_example")
1388+
.collection("example")
1389+
.find(None, None)
1390+
.await?;
1391+
// End 1.
1392+
1393+
// Start 2. Strict option
1394+
let mut options = ClientOptions::parse(&uri).await?;
1395+
let server_api = ServerApi::builder()
1396+
.version(ServerApiVersion::Version1)
1397+
.strict(true)
1398+
.build();
1399+
options.server_api = Some(server_api);
1400+
let client = Client::with_options(options)?;
1401+
1402+
let find_options = FindOptions::builder()
1403+
.cursor_type(CursorType::Tailable)
1404+
.build();
1405+
let cursor = client
1406+
.database("versioned_api_example")
1407+
.collection("example")
1408+
.find(None, find_options)
1409+
.await
1410+
.expect_err("should fail");
1411+
// End 2.
1412+
1413+
// Start 3. deprecationErrors option
1414+
let mut options = ClientOptions::parse(&uri).await?;
1415+
let server_api = ServerApi::builder()
1416+
.version(ServerApiVersion::Version1)
1417+
.deprecation_errors(true)
1418+
.build();
1419+
options.server_api = Some(server_api);
1420+
let client = Client::with_options(options)?;
1421+
// End 3.
1422+
1423+
Ok(())
1424+
}
1425+
13671426
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
13681427
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
13691428
async fn test() {
1429+
let _guard: RwLockReadGuard<_> = LOCK.run_concurrently().await;
1430+
13701431
let client = TestClient::new().await;
13711432
let coll = client
13721433
.database("documentation_examples")
@@ -1383,4 +1444,5 @@ async fn test() {
13831444
projection_examples(&coll).await.unwrap();
13841445
update_examples(&coll).await.unwrap();
13851446
delete_examples(&coll).await.unwrap();
1447+
versioned_api_examples().await.unwrap();
13861448
}

src/test/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod client;
55
mod coll;
66
mod cursor;
77
mod db;
8+
#[cfg(not(feature = "sync"))]
89
mod documentation_examples;
910
mod spec;
1011
mod util;

0 commit comments

Comments
 (0)