1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::Client;
use super::{export_doc, options_doc};
impl Client {
/// Shut down this `Client`, terminating background thread workers and closing connections.
/// Using this method is not required under most circumstances (resources will be cleaned up in
/// the background when dropped) but can be needed when creating `Client`s in a loop or precise
/// control of lifespan timing is required. This will wait for any live handles to
/// server-side resources (see below) to be dropped and any associated server-side
/// operations to finish.
///
/// IMPORTANT: Any live resource handles that are not dropped will cause this method to wait
/// indefinitely. It's strongly recommended to structure your usage to avoid this, e.g. by
/// only using those types in shorter-lived scopes than the `Client`. If this is not possible,
/// see [`immediate`](Shutdown::immediate). For example:
///
/// ```rust
/// # use mongodb::{Client, error::Result, gridfs::GridFsBucket};
/// async fn upload_data(bucket: &GridFsBucket) -> Result<()> {
/// let stream = bucket.open_upload_stream("test").await?;
/// // .. write to the stream ..
/// # Ok(())
/// }
///
/// # async fn run() -> Result<()> {
/// let client = Client::with_uri_str("mongodb://example.com").await?;
/// let bucket = client.database("test").gridfs_bucket(None);
/// upload_data(&bucket).await;
/// client.shutdown().await;
/// // Background cleanup work from `upload_data` is guaranteed to have run.
/// # Ok(())
/// # }
/// ```
///
/// If the handle is used in the same scope as `shutdown`, explicit `drop` may be needed:
///
/// ```rust
/// # use mongodb::{Client, error::Result};
/// # async fn run() -> Result<()> {
/// let client = Client::with_uri_str("mongodb://example.com").await?;
/// let bucket = client.database("test").gridfs_bucket(None);
/// let stream = bucket.open_upload_stream("test").await?;
/// // .. write to the stream ..
/// drop(stream);
/// client.shutdown().await;
/// // Background cleanup work for `stream` is guaranteed to have run.
/// # Ok(())
/// # }
/// ```
///
/// Calling any methods on clones of this `Client` or derived handles after this will return
/// errors.
///
/// Handles to server-side resources are `Cursor`, `SessionCursor`, `Session`, or
/// `GridFsUploadStream`.
///
/// `await` will return `()`.
#[options_doc(shutdown)]
pub fn shutdown(self) -> Shutdown {
Shutdown {
client: self,
immediate: false,
}
}
}
#[cfg(feature = "sync")]
impl crate::sync::Client {
/// Shut down this `Client`, terminating background thread workers and closing connections.
/// Using this method is not required under most circumstances (resources will be cleaned up in
/// the background when dropped) but can be needed when creating `Client`s in a loop or precise
/// control of lifespan timing is required. This will wait for any live handles to
/// server-side resources (see below) to be dropped and any associated server-side
/// operations to finish.
///
/// IMPORTANT: Any live resource handles that are not dropped will cause this method to wait
/// indefinitely. It's strongly recommended to structure your usage to avoid this, e.g. by
/// only using those types in shorter-lived scopes than the `Client`. If this is not possible,
/// see [`immediate`](Shutdown::immediate). For example:
///
/// ```rust
/// # use mongodb::{sync::{Client, gridfs::GridFsBucket}, error::Result};
/// fn upload_data(bucket: &GridFsBucket) -> Result<()> {
/// let stream = bucket.open_upload_stream("test").run()?;
/// // .. write to the stream ..
/// # Ok(())
/// }
///
/// # fn run() -> Result<()> {
/// let client = Client::with_uri_str("mongodb://example.com")?;
/// let bucket = client.database("test").gridfs_bucket(None);
/// upload_data(&bucket)?;
/// client.shutdown();
/// // Background cleanup work from `upload_data` is guaranteed to have run.
/// # Ok(())
/// # }
/// ```
///
/// If the handle is used in the same scope as `shutdown`, explicit `drop` may be needed:
///
/// ```rust
/// # use mongodb::{sync::Client, error::Result};
/// # fn run() -> Result<()> {
/// let client = Client::with_uri_str("mongodb://example.com")?;
/// let bucket = client.database("test").gridfs_bucket(None);
/// let stream = bucket.open_upload_stream("test").run()?;
/// // .. write to the stream ..
/// drop(stream);
/// client.shutdown();
/// // Background cleanup work for `stream` is guaranteed to have run.
/// # Ok(())
/// # }
/// ```
///
/// Calling any methods on clones of this `Client` or derived handles after this will return
/// errors.
///
/// Handles to server-side resources are `Cursor`, `SessionCursor`, `Session`, or
/// `GridFsUploadStream`.
///
/// [`run`](Shutdown::run) will return `()`.
#[options_doc(shutdown, sync)]
pub fn shutdown(self) -> Shutdown {
self.async_client.shutdown()
}
}
/// Shut down this `Client`, terminating background thread workers and closing connections. Create
/// by calling [`Client::shutdown`].
#[must_use]
pub struct Shutdown {
pub(crate) client: Client,
pub(crate) immediate: bool,
}
#[export_doc(shutdown)]
impl Shutdown {
/// If `true`, execution will not wait for pending resources to be cleaned up,
/// which may cause both client-side errors and server-side resource leaks. Defaults to
/// `false`.
pub fn immediate(mut self, value: bool) -> Self {
self.immediate = value;
self
}
}
// IntoFuture impl in src/client/action/shutdown.rs