Skip to content

Commit e03e24d

Browse files
committed
chore(testcontainers): Add documentation to the container feature
Signed-off-by: Raphael Höser <[email protected]>
1 parent ddc584d commit e03e24d

File tree

4 files changed

+135
-20
lines changed

4 files changed

+135
-20
lines changed

Cargo.lock

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ eventsourcingdb-client-rust = {path = ".", features = ["testcontainer"]}
1717
reqwest = "0.12.15"
1818
testcontainers = { version = "0.24.0", features = ["http_wait"] }
1919
tokio = { version = "1.44.2", features = ["full"] }
20+
tokio-test = "0.4.4"
21+
22+
# This is metadata required for working docs on docs.rs
23+
[package.metadata.docs.rs]
24+
features = ["testcontainer"]

src/container.rs

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
//! This module holds the optional testcontainer utility functions of the SDK.
22
//!
3-
//! It uses the [testcontainers](https://docs.rs/testcontainers/latest/testcontainers/) crate to start a test container for the [EventSourcingDB](https://www.eventsourcingdb.io/).
3+
//! It uses the [testcontainers] crate to start a test container for the [EventSourcingDB](https://www.eventsourcingdb.io/).
4+
//!
45
//! It uses the builder pattern to configure the container and start it.
6+
//!
7+
//! # How to use
8+
//!
9+
//! ## Shortcut suitable for most use cases
10+
//! This starts a container with the default settings which is most likely what you want.
11+
//! ```
12+
//! # use eventsourcingdb_client_rust::container::Container;
13+
//! # tokio_test::block_on(async {
14+
//! let container = Container::start_default().await;
15+
//! // let client = container.get_client().await;
16+
//! # });
17+
//! ```
18+
//!
19+
//! ## Custom configuration
20+
//! This allows you to configure the container to your needs.
21+
//! ```
22+
//! # use eventsourcingdb_client_rust::container::Container;
23+
//! # tokio_test::block_on(async {
24+
//! let container = Container::builder()
25+
//! .with_image_tag("v1.0.0")
26+
//! .with_port(3000)
27+
//! .with_api_token("mysecrettoken")
28+
//! .start().await;
29+
//! // let client = container.get_client().await;
30+
//! # });
31+
//! ```
32+
//!
33+
//! ## Stopping the container
34+
//! The container will be stopped automatically when it is dropped.
35+
//! You can also stop it manually by calling the [Container::stop] method.
536
use testcontainers::{
637
ContainerAsync, GenericImage,
738
core::{ContainerPort, ImageExt, WaitFor, wait::HttpWaitStrategy},
@@ -11,8 +42,20 @@ use url::{Host, Url};
1142

1243
use crate::error::ContainerError;
1344

14-
/// Builder for the test container
15-
/// You should not use this directly, but use the `Container::builder()` method instead.
45+
/// Builder for the [Container].
46+
///
47+
/// **You should not use this directly**, but use the [Container::builder] method instead.
48+
///
49+
/// By default this container is the same as running this:
50+
/// ```
51+
/// # use eventsourcingdb_client_rust::container::Container;
52+
/// # tokio_test::block_on(async {
53+
/// let builder = Container::builder()
54+
/// .with_image_tag("latest")
55+
/// .with_port(3000)
56+
/// .with_api_token("secret");
57+
/// # });
58+
/// ```
1659
#[derive(Debug, Clone)]
1760
pub struct ContainerBuilder {
1861
image_name: String,
@@ -33,33 +76,40 @@ impl Default for ContainerBuilder {
3376
}
3477

3578
impl ContainerBuilder {
36-
/// Set the image tag to use for the container#
79+
/// Set the image tag to use for the container.
3780
#[must_use]
3881
pub fn with_image_tag(mut self, tag: &str) -> Self {
3982
self.image_tag = tag.to_string();
4083
self
4184
}
4285

43-
/// Set the API token to use for the container
86+
/// Set the API token to use for the container.
4487
#[must_use]
4588
pub fn with_api_token(mut self, token: &str) -> Self {
4689
self.api_token = token.to_string();
4790
self
4891
}
4992

50-
/// Set the port to use for the container
93+
/// Set the port to use for the container.
94+
///
95+
/// This is the port that will be exposed from the container to the host.
96+
/// It will be mapped to a random port on the host that you can connect to.
97+
/// To find that port, use the [Container::get_mapped_port] method.
5198
#[must_use]
5299
pub fn with_port(mut self, port: impl Into<ContainerPort>) -> Self {
53100
self.internal_port = port.into();
54101
self
55102
}
56103

57-
/// Start the test container
104+
/// Start the test container.
58105
///
59106
/// This call will transform the builder into a running container.
107+
/// It takes care of starting the container and waiting for it to be ready by waiting for the
108+
/// [ping](https://docs.eventsourcingdb.io/reference/api-overview/#authentication)
109+
/// endpoint to respond since that doesn't require authentication.
60110
///
61111
/// # Errors
62-
/// This function will return an error if the container could not be started
112+
/// This function will return an error if the container could not be started.
63113
pub async fn start(self) -> Result<Container, ContainerError> {
64114
Ok(Container {
65115
internal_port: self.internal_port,
@@ -86,7 +136,20 @@ impl ContainerBuilder {
86136
}
87137
}
88138

89-
/// A running test container for the [EventSourcingDB](https://www.eventsourcingdb.io/)
139+
/// A running test container for the [EventSourcingDB](https://www.eventsourcingdb.io/).
140+
///
141+
/// Aside from managing the container, this struct also provides methods to get the data needed to connect to
142+
/// the database or even a fully configured client.
143+
///
144+
/// You'll most likely want to use the [Container::start_default] method to create a new container instance for your tests.
145+
/// For more details, see the [crate::container] module documentation.
146+
/// ```
147+
/// # use eventsourcingdb_client_rust::container::Container;
148+
/// # tokio_test::block_on(async {
149+
/// let container = Container::start_default().await;
150+
/// // let client = container.get_client().await;
151+
/// # });
152+
/// ```
90153
#[derive(Debug)]
91154
pub struct Container {
92155
container: ContainerAsync<GenericImage>,
@@ -95,29 +158,38 @@ pub struct Container {
95158
}
96159

97160
impl Container {
98-
/// Create a new container builder instance to configure the container
161+
/// Create a new container builder instance to configure the container.
162+
/// The returned builder starts with the default settings and is the same as calling [ContainerBuilder::default].
163+
/// This is the recommended way to create a new [ContainerBuilder] instance.
99164
#[must_use]
100165
pub fn builder() -> ContainerBuilder {
101166
ContainerBuilder::default()
102167
}
103168

104-
/// Shortcut method to start the container with default settings
169+
/// Shortcut method to start the container with default settings.
170+
///
171+
/// This is the same as calling [Container::builder] and then [ContainerBuilder::start].
172+
/// In most cases this will create a contaienr with the latest image tag and a working configuration.
105173
///
106174
/// # Errors
107175
/// This functions returns the errors of `ContainerBuilder::start()`
108176
pub async fn start_default() -> Result<Container, ContainerError> {
109177
Self::builder().start().await
110178
}
111179

112-
/// Get the host of the container
180+
/// Get the host of the container.
181+
///
182+
/// This is the host that you can use to connect to the database. In most cases this will be `localhost`.
113183
///
114184
/// # Errors
115185
/// This function will return an error if the container is not running (e.g. because it crashed) or if the host could not be retrieved
116186
pub async fn get_host(&self) -> Result<Host, ContainerError> {
117187
Ok(self.container.get_host().await?)
118188
}
119189

120-
/// Get the mapped port for the database
190+
/// Get the mapped port for the database.
191+
///
192+
/// This is the port that you can use to connect to the database. This will be a random port that is mapped to the internal port configured via [ContainerBuilder::with_port].
121193
///
122194
/// # Errors
123195
/// This function will return an error if the container is not running (e.g. because it crashed) or if the host could not be retrieved
@@ -128,7 +200,7 @@ impl Container {
128200
.await?)
129201
}
130202

131-
/// Get the complete base URL for the database
203+
/// Get the complete http base URL for the database.
132204
///
133205
/// # Errors
134206
/// This function will return an error if the container is not running (e.g. because it crashed) or if the host could not be retrieved
@@ -138,7 +210,7 @@ impl Container {
138210
Ok(Url::parse(&format!("http://{host}:{port}"))?)
139211
}
140212

141-
/// Get the API token for the database
213+
/// Get the API token for the database.
142214
///
143215
/// # Errors
144216
/// This function will return an error if the container is not running (e.g. because it crashed) or if the host could not be retrieved
@@ -147,7 +219,7 @@ impl Container {
147219
self.api_token.as_str()
148220
}
149221

150-
/// Check if the container is running
222+
/// Check if the container is running.
151223
///
152224
/// Since we make sure the container is running via the typesystem, this will always return true.
153225
/// This method is still included to match the interface of the Go SDK.

src/error.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
//! This module contains all error types of the SDK.
22
3-
/// Error type for the test container
3+
/// Error type for the [crate::container] feature.
44
#[cfg(feature = "testcontainer")]
55
#[derive(Debug, thiserror::Error)]
66
pub enum ContainerError {
7-
/// Testcontainers error
7+
/// This error is returned when anything goes wrong with the testcontainers crate.
8+
/// If you experience this error, a likely cause is that your docker daemon is not running.
9+
/// Please check if you can run `docker ps` in your terminal.
810
#[error("Testcontainers error: {0}")]
911
TestcontainersError(#[from] testcontainers::TestcontainersError),
10-
/// URL parsing error
12+
/// This error should never happen. If you experience this error, please let us know as it's likely a bug in the SDK.
1113
#[error("URL parsing error: {0}")]
1214
URLParseError(#[from] url::ParseError),
1315
}

0 commit comments

Comments
 (0)