Skip to content

Commit a8345db

Browse files
authored
RUST-1909 3.0 migration guide (#1078)
1 parent 31d9a37 commit a8345db

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

migration-3.0.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Migrating from 2.x to 3.0
2+
3.0 introduces a wide variety of improvements that required backwards-incompatible API changes; in most cases these changes should require only minor updates in application code.
3+
4+
## Fluent API
5+
Async methods that accepted options have been updated to allow the individual options to be given directly in line with the call to reduce required boilerplate. A session can now also be set using a chained method rather than a distinct `_with_session` method.
6+
7+
In 2.x:
8+
```rust
9+
// Without options
10+
let cursor = collection.find(doc! { "status": "A" }, None).await?;
11+
// With options
12+
let cursor = collection
13+
.find(
14+
doc! { "status": "A" },
15+
FindOptions::builder()
16+
.projection(doc! {
17+
"status": 0,
18+
"instock": 0,
19+
})
20+
.build(),
21+
)
22+
.await?;
23+
// With options and a session
24+
let cursor = collection
25+
.find_with_session(
26+
doc! { "status": "A" },
27+
FindOptions::builder()
28+
.projection(doc! {
29+
"status": 0,
30+
"instock": 0,
31+
})
32+
.build(),
33+
&mut session,
34+
)
35+
.await?;
36+
```
37+
38+
In 3.0:
39+
```rust
40+
// Without options
41+
let cursor = collection.find(doc! { "status": "A" }).await?;
42+
// With options
43+
let cursor = collection
44+
.find(doc! { "status": "A" })
45+
.projection(doc! {
46+
"status": 0,
47+
"instock": 0,
48+
})
49+
.await?;
50+
// With options and a session
51+
let cursor = collection
52+
.find(doc! { "status": "A" })
53+
.projection(doc! {
54+
"status": 0,
55+
"instock": 0,
56+
})
57+
.session(&mut session)
58+
.await?;
59+
```
60+
61+
If an option needs to be conditionally set, the `optional` convenience method can be used:
62+
```rust
63+
async fn run_find(opt_projection: Option<Document>) -> Result<()> {
64+
let cursor = collection
65+
.find(doc! { "status": "A" })
66+
.optional(opt_projection, |f, p| f.projection(p))
67+
.await?;
68+
...
69+
}
70+
```
71+
72+
For those cases where options still need to be constructed independently, the `with_options` method is provided:
73+
```rust
74+
let options = FindOptions::builder()
75+
.projection(doc! {
76+
"status": 0,
77+
"instock": 0,
78+
})
79+
.build();
80+
let cursor = collection
81+
.find(doc! { "status": "A" })
82+
.with_options(options)
83+
.await?;
84+
```
85+
86+
## Listening for Events
87+
The 2.x event API required that applications provide an `Arc<dyn CmapEventHandler>` (or `CommandEventHandler` / `SdamEventHandler`). This required a fair amount of boilerplate, especially for simpler handlers (e.g. logging), and did not provide any way for event handlers to perform async work. To address both of those, 3.0 introduces the `EventHandler` type.
88+
89+
In 2.x:
90+
```rust
91+
struct CmapEventLogger;
92+
impl CmapEventHandler for CmapEventLogger {
93+
fn handle_pool_created_event(&self, event: PoolCreatedEvent) {
94+
println!("{:?}", event);
95+
}
96+
/// repeat for handle_pool_ready_event, etc.
97+
}
98+
let options = ClientOptions::builder()
99+
.cmap_event_handler(Arc::new(CmapEventLogger))
100+
.build();
101+
```
102+
103+
In 3.0:
104+
```rust
105+
let options = ClientOptions::builder()
106+
.cmap_event_handler(EventHandler::callback(|ev| println!("{:?}", ev)))
107+
.build();
108+
```
109+
110+
`EventHandler` can be constructed from a callback, async callback, or an async channel sender. To ease migration, it can also be constructed from the now-deprecated 2.x `CmapEventHandler`/`CommandEventHandler`/`SdamEventHandler` types.
111+
112+
## Async Runtime
113+
2.x supported both `tokio` (default) and `async-std` as async runtimes. Maintaining this dual support was a significant ongoing development cost, and with both Rust mongodb driver usage and overall Rust ecosystem usage heavily favoring `tokio`, 3.0 only supports `tokio`.
114+
115+
## Future-proof Features
116+
Starting in 3.0, if the Rust driver is compiled with `no-default-features` it will require the use of a `compat` feature; this provides the flexibility to make features optional in future versions of the driver. Lack of this had prevented `rustls` and `dns-resolution` from becoming optional in 2.x; they are now optional in 3.0.
117+
118+
In addition, we have removed the various `bson-*` features from the driver, as those can be selected by including `bson` as a direct dependency.
119+
120+
## ReadConcern / WriteConcern Helpers
121+
The Rust driver provides convenience helpers for constructing commonly used read or write concerns (e.g. "majority"). In 2.x, these were an overlapping mix of constants and methods (`ReadConcern::MAJORITY` and `ReadConcern::majority()`). In 3.0, these are only provided as methods.
122+
123+
## `Send + Sync` Constraints on `Collection`
124+
In 2.x, whether a method on `Collection<T>` required `T: Send` or `T: Send + Sync` was ad-hoc and inconsistent. Whether these constraints were required for compilation depended on details like whether the transitive call graph of the implementation held a value of `T` over an `await` point, which could easily change as development continued. For consistency and to allow for future development, in 3.0 `Collection<T>` requires `T: Send + Sync`.
125+
126+
## Compression Option Behind Feature Flags
127+
In 2.x, the `ClientOptions::compressor` field was always present, but with no compressor features selected could not be populated. For simplicity and consistency with our other optional features, in 3.0 that field will not be present if no compressor features are enabled.
128+
129+
## Optional `ReadPreferenceOptions`
130+
In 3.0, the `ReadPreferenceOptions` fields of `ReadPreference` arms are now `Option<ReadPreferenceOptions>`.
131+
132+
## `human_readable_serialization` Option Removed in favor of `HumanReadable`
133+
In some uncommon cases, applications prefer user data types to be serialized in their human-readable form; the `CollectionOptions::human_readable_serialization` option enabled that. In 3.x, this option has been removed; the `bson::HumanReadable` wrapper type can be used to achieve the same effect.
134+
135+
## Consistent Defaults for `TypedBuilder` Implementations
136+
In 2.x, most but not all option struct builders would allow value conversion via `Into` and would use the `default()` value if not set; this is now the behavior across all option struct builders.
137+
138+
## `comment_bson` is now `comment`
139+
In 2.x, the `AggregateOptions`, `FindOptions`, and `FindOneOptions` structs had both `comment_bson` and legacy `comment` fields. In 3.x, `comment_bson` has been renamed to `comment`, replacing the legacy field.

0 commit comments

Comments
 (0)