|
1 | 1 | use bson::Document;
|
2 | 2 | use futures::TryStreamExt;
|
| 3 | +use semver::Version; |
3 | 4 | use tokio::sync::RwLockReadGuard;
|
4 | 5 |
|
5 | 6 | use crate::{
|
6 | 7 | bson::{doc, Bson},
|
7 |
| - error::Result, |
| 8 | + error::{ErrorKind, Result}, |
8 | 9 | options::{ClientOptions, FindOptions, ServerApi, ServerApiVersion},
|
9 | 10 | test::{TestClient, DEFAULT_URI, LOCK},
|
10 | 11 | Client,
|
@@ -1369,12 +1370,19 @@ async fn delete_examples(collection: &Collection<Document>) -> Result<()> {
|
1369 | 1370 |
|
1370 | 1371 | #[allow(unused_variables)]
|
1371 | 1372 | #[cfg(not(feature = "sync"))]
|
1372 |
| -async fn versioned_api_examples() -> Result<()> { |
| 1373 | +async fn versioned_api_examples() -> std::result::Result<(), Box<dyn std::error::Error>> { |
1373 | 1374 | let setup_client = TestClient::new().await;
|
1374 | 1375 | if setup_client.server_version_lt(4, 9) {
|
1375 | 1376 | println!("skipping versioned API examples due to unsupported server version");
|
1376 | 1377 | return Ok(());
|
1377 | 1378 | }
|
| 1379 | + if setup_client.is_sharded() && setup_client.server_version <= Version::new(5, 0, 2) { |
| 1380 | + // See SERVER-58794. |
| 1381 | + println!( |
| 1382 | + "skipping versioned API examples due to unsupported server version on sharded topology" |
| 1383 | + ); |
| 1384 | + return Ok(()); |
| 1385 | + } |
1378 | 1386 |
|
1379 | 1387 | let uri = DEFAULT_URI.clone();
|
1380 | 1388 | // Start Versioned API Example 1
|
@@ -1414,6 +1422,75 @@ async fn versioned_api_examples() -> Result<()> {
|
1414 | 1422 | let client = Client::with_options(options)?;
|
1415 | 1423 | // End Versioned API Example 4
|
1416 | 1424 |
|
| 1425 | + let mut options = ClientOptions::parse(&uri).await?; |
| 1426 | + let server_api = ServerApi::builder() |
| 1427 | + .version(ServerApiVersion::V1) |
| 1428 | + .strict(true) |
| 1429 | + .build(); |
| 1430 | + options.server_api = Some(server_api); |
| 1431 | + let client = Client::with_options(options)?; |
| 1432 | + let db = client.database("versioned-api-migration-examples"); |
| 1433 | + db.collection::<Document>("sales").drop(None).await?; |
| 1434 | + |
| 1435 | + use std::{error::Error, result::Result}; |
| 1436 | + // Start Versioned API Example 5 |
| 1437 | + // With the `bson-chrono-0_4` feature enabled, this function can be dropped in favor of using |
| 1438 | + // `chrono::DateTime` values directly. |
| 1439 | + fn iso_date(text: &str) -> Result<bson::DateTime, Box<dyn Error>> { |
| 1440 | + let chrono_dt = chrono::DateTime::parse_from_rfc3339(text)?; |
| 1441 | + Ok(bson::DateTime::from_millis(chrono_dt.timestamp_millis())) |
| 1442 | + } |
| 1443 | + db.collection("sales").insert_many(vec![ |
| 1444 | + doc! { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : iso_date("2021-01-01T08:00:00Z")? }, |
| 1445 | + doc! { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : iso_date("2021-02-03T09:05:00Z")? }, |
| 1446 | + doc! { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : iso_date("2021-02-03T09:00:00Z")? }, |
| 1447 | + doc! { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : iso_date("2021-02-15T08:00:00Z")? }, |
| 1448 | + doc! { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : iso_date("2021-02-15T09:05:00Z")? }, |
| 1449 | + doc! { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : iso_date("2021-02-15T12:05:10Z")? }, |
| 1450 | + doc! { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : iso_date("2021-02-15T14:12:12Z")? }, |
| 1451 | + doc! { "_id" : 8, "item" : "abc", "price" : 10, "quantity" : 5, "date" : iso_date("2021-03-16T20:20:13Z")? } |
| 1452 | + ], None).await?; |
| 1453 | + // End Versioned API Example 5 |
| 1454 | + |
| 1455 | + // Start Versioned API Example 6 |
| 1456 | + let result = db |
| 1457 | + .run_command( |
| 1458 | + doc! { |
| 1459 | + "count": "sales" |
| 1460 | + }, |
| 1461 | + None, |
| 1462 | + ) |
| 1463 | + .await; |
| 1464 | + if let Err(err) = &result { |
| 1465 | + println!("{:#?}", err.kind); |
| 1466 | + // Prints: |
| 1467 | + // Command( |
| 1468 | + // CommandError { |
| 1469 | + // code: 323, |
| 1470 | + // code_name: "APIStrictError", |
| 1471 | + // message: "Provided apiStrict:true, but the command count is not in API Version 1. Information on supported commands and migrations in API Version 1 can be found at https://dochub.mongodb.org/core/manual-versioned-api", |
| 1472 | + // }, |
| 1473 | + // ) |
| 1474 | + } |
| 1475 | + // End Versioned API Example 6 |
| 1476 | + if let ErrorKind::Command(ref err) = *result.as_ref().unwrap_err().kind { |
| 1477 | + assert_eq!(err.code, 323); |
| 1478 | + assert_eq!(err.code_name, "APIStrictError".to_string()); |
| 1479 | + } else { |
| 1480 | + panic!("invalid result {:?}", result); |
| 1481 | + }; |
| 1482 | + |
| 1483 | + // Start Versioned API Example 7 |
| 1484 | + let count = db |
| 1485 | + .collection::<Document>("sales") |
| 1486 | + .count_documents(None, None) |
| 1487 | + .await?; |
| 1488 | + // End Versioned API Example 7 |
| 1489 | + |
| 1490 | + // Start Versioned API Example 8 |
| 1491 | + assert_eq!(count, 8); |
| 1492 | + // End Versioned API Example 8 |
| 1493 | + |
1417 | 1494 | Ok(())
|
1418 | 1495 | }
|
1419 | 1496 |
|
|
0 commit comments