diff --git a/core/lib/src/local/client.rs b/core/lib/src/local/client.rs index 4a6a8320..17875ef8 100644 --- a/core/lib/src/local/client.rs +++ b/core/lib/src/local/client.rs @@ -10,16 +10,17 @@ use error::LaunchError; /// /// # Usage /// -/// A `Client` is constructed via the [`new`] or [`untracked`] methods from an -/// already constructed `Rocket` instance. Once a value of `Client` has been -/// constructed, the [`LocalRequest`] constructor methods ([`get`], [`put`], -/// [`post`], and so on) can be used to create a `LocalRequest` for dispatching. +/// A `Client` is constructed via the [`new()`] or [`untracked()`] methods from +/// an already constructed `Rocket` instance. Once a value of `Client` has been +/// constructed, the [`LocalRequest`] constructor methods ([`get()`], [`put()`], +/// [`post()`], and so on) can be used to create a `LocalRequest` for +/// dispatching. /// /// See the [top-level documentation](::local) for more usage information. /// /// ## Cookie Tracking /// -/// A `Client` constructed using [`new`] propagates cookie changes made by +/// A `Client` constructed using [`new()`] propagates cookie changes made by /// responses to previously dispatched requests. In other words, if a previously /// dispatched request resulted in a response that adds a cookie, any future /// requests will contain that cookie. Similarly, cookies removed by a response @@ -28,9 +29,24 @@ use error::LaunchError; /// This is typically the desired mode of operation for a `Client` as it removes /// the burden of manually tracking cookies. Under some circumstances, however, /// disabling this tracking may be desired. In these cases, use the -/// [`untracked`](Client::untracked()) constructor to create a `Client` that +/// [`untracked()`](Client::untracked()) constructor to create a `Client` that /// _will not_ track cookies. /// +/// ### Synchronization +/// +/// While `Client` implements `Sync`, using it in a multithreaded environment +/// while tracking cookies can result in surprising, non-deterministic behavior. +/// This is because while cookie modifications are serialized, the exact +/// ordering depends on when requests are dispatched. Specifically, when cookie +/// tracking is enabled, all request dispatches are serialized, which in-turn +/// serializes modifications to the internally tracked cookies. +/// +/// If possible, refrain from sharing a single instance of `Client` across +/// multiple threads. Instead, prefer to create a unique instance of `Client` +/// per thread. If it's not possible, ensure that either you are not depending +/// on cookies, the ordering of their modifications, or both, or have arranged +/// for dispatches to occur in a deterministic ordering. +/// /// ## Example /// /// The following snippet creates a `Client` from a `Rocket` instance and @@ -46,11 +62,11 @@ use error::LaunchError; /// .dispatch(); /// ``` /// -/// [`new`]: #method.new -/// [`untracked`]: #method.untracked -/// [`get`]: #method.get -/// [`put`]: #method.put -/// [`post`]: #method.post +/// [`new()`]: #method.new +/// [`untracked()`]: #method.untracked +/// [`get()`]: #method.get +/// [`put()`]: #method.put +/// [`post()`]: #method.post pub struct Client { rocket: Rocket, crate cookies: Option>,