From d0a84df2d2716fe106f6aeb13e9bdf72ffbf9bf5 Mon Sep 17 00:00:00 2001 From: Leynos Date: Tue, 12 Aug 2025 12:06:54 +0100 Subject: [PATCH 1/4] Document compile-time binding requirement --- docs/server/configuration.md | 7 ++++--- src/server/config/mod.rs | 2 ++ src/server/runtime.rs | 13 +++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/server/configuration.md b/docs/server/configuration.md index c93582b2..c32693c1 100644 --- a/docs/server/configuration.md +++ b/docs/server/configuration.md @@ -1,8 +1,9 @@ # Server configuration -`WireframeServer` provides a builder API for adjusting runtime behaviour. This -guide focuses on tuning the exponential backoff used when accepting connections -fails. +`WireframeServer` provides a builder API for adjusting runtime behaviour. The +server employs a typestate to ensure that binding occurs before runtime: +unbound servers do not expose `run` methods. This guide focuses on tuning the +exponential backoff used when accepting connections fails. ## Accept loop backoff diff --git a/src/server/config/mod.rs b/src/server/config/mod.rs index cd742850..c360fa4b 100644 --- a/src/server/config/mod.rs +++ b/src/server/config/mod.rs @@ -7,6 +7,8 @@ //! server may be constructed unbound and later bound using //! [`bind`](WireframeServer::bind) or //! [`bind_existing_listener`](WireframeServer::bind_existing_listener) on [`Unbound`] servers. +//! The `run` methods are only available once the server is bound, ensuring at +//! compile time that the binding step cannot be skipped. use core::marker::PhantomData; diff --git a/src/server/runtime.rs b/src/server/runtime.rs index 95df19ae..52a5ac9e 100644 --- a/src/server/runtime.rs +++ b/src/server/runtime.rs @@ -74,6 +74,19 @@ where /// # } /// ``` /// + /// Attempting to run a server without binding fails to compile: + /// + /// ```compile_fail + /// use wireframe::{app::WireframeApp, server::WireframeServer}; + /// + /// async fn try_run() { + /// WireframeServer::new(|| WireframeApp::default()) + /// .run() + /// .await + /// .unwrap(); + /// } + /// ``` + /// /// # Errors /// /// Returns a [`ServerError`] if runtime initialisation fails. From 73c11648cb31bcdd99de3de5484610450a9e5467 Mon Sep 17 00:00:00 2001 From: Leynos Date: Tue, 12 Aug 2025 17:38:10 +0100 Subject: [PATCH 2/4] Clarify binding requirement examples --- docs/server/configuration.md | 12 ++++++++++++ src/server/config/mod.rs | 4 ++-- src/server/runtime.rs | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/server/configuration.md b/docs/server/configuration.md index c32693c1..5238c9e9 100644 --- a/docs/server/configuration.md +++ b/docs/server/configuration.md @@ -5,6 +5,18 @@ server employs a typestate to ensure that binding occurs before runtime: unbound servers do not expose `run` methods. This guide focuses on tuning the exponential backoff used when accepting connections fails. +```rust +use wireframe::{app::WireframeApp, server::WireframeServer}; + +# #[tokio::main] +# async fn main() -> Result<(), wireframe::server::ServerError> { +let server = WireframeServer::new(|| WireframeApp::default()) + .bind(([127, 0, 0, 1], 0).into())?; +server.run().await?; +# Ok(()) +# } +``` + ## Accept loop backoff The accept loop retries failed `accept()` calls using exponential backoff. diff --git a/src/server/config/mod.rs b/src/server/config/mod.rs index c360fa4b..e27528b6 100644 --- a/src/server/config/mod.rs +++ b/src/server/config/mod.rs @@ -7,8 +7,8 @@ //! server may be constructed unbound and later bound using //! [`bind`](WireframeServer::bind) or //! [`bind_existing_listener`](WireframeServer::bind_existing_listener) on [`Unbound`] servers. -//! The `run` methods are only available once the server is bound, ensuring at -//! compile time that the binding step cannot be skipped. +//! The `run` methods are available only once the server is [`Bound`], enforcing +//! at compile time that the binding step cannot be skipped. use core::marker::PhantomData; diff --git a/src/server/runtime.rs b/src/server/runtime.rs index 52a5ac9e..1df74093 100644 --- a/src/server/runtime.rs +++ b/src/server/runtime.rs @@ -76,6 +76,9 @@ where /// /// Attempting to run a server without binding fails to compile: /// + /// Binding specifies the network address for the server to listen on. + /// It is required so the server knows where to accept incoming connections. + /// /// ```compile_fail /// use wireframe::{app::WireframeApp, server::WireframeServer}; /// From caed76b4dedac7e186a9f7bd260d2ac7a7433a6a Mon Sep 17 00:00:00 2001 From: Leynos Date: Tue, 12 Aug 2025 23:50:05 +0100 Subject: [PATCH 3/4] Apply review feedback for binding docs --- docs/server/configuration.md | 2 +- src/server/config/mod.rs | 7 ++++--- src/server/runtime.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/server/configuration.md b/docs/server/configuration.md index 5238c9e9..388df76d 100644 --- a/docs/server/configuration.md +++ b/docs/server/configuration.md @@ -5,7 +5,7 @@ server employs a typestate to ensure that binding occurs before runtime: unbound servers do not expose `run` methods. This guide focuses on tuning the exponential backoff used when accepting connections fails. -```rust +```rust,no_run use wireframe::{app::WireframeApp, server::WireframeServer}; # #[tokio::main] diff --git a/src/server/config/mod.rs b/src/server/config/mod.rs index e27528b6..19694af3 100644 --- a/src/server/config/mod.rs +++ b/src/server/config/mod.rs @@ -6,9 +6,10 @@ //! behaviour is customized via the [`preamble`](self::preamble) module. The //! server may be constructed unbound and later bound using //! [`bind`](WireframeServer::bind) or -//! [`bind_existing_listener`](WireframeServer::bind_existing_listener) on [`Unbound`] servers. -//! The `run` methods are available only once the server is [`Bound`], enforcing -//! at compile time that the binding step cannot be skipped. +//! [`bind_existing_listener`](WireframeServer::bind_existing_listener) on +//! [`Unbound`] servers. The `run` methods are available only once the server +//! is [`Bound`](super::Bound), enforcing at compile time that the binding step +//! cannot be skipped. use core::marker::PhantomData; diff --git a/src/server/runtime.rs b/src/server/runtime.rs index 1df74093..491be290 100644 --- a/src/server/runtime.rs +++ b/src/server/runtime.rs @@ -86,7 +86,7 @@ where /// WireframeServer::new(|| WireframeApp::default()) /// .run() /// .await - /// .unwrap(); + /// .expect("unbound servers do not expose run()"); /// } /// ``` /// From 8814485dd1d4454a90c2f2ca17d3bad998ffab9d Mon Sep 17 00:00:00 2001 From: Leynos Date: Wed, 13 Aug 2025 22:47:54 +0100 Subject: [PATCH 4/4] Clarify binding typestate docs --- docs/server/configuration.md | 6 +++--- src/server/config/mod.rs | 9 +++++---- src/server/runtime.rs | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/docs/server/configuration.md b/docs/server/configuration.md index 388df76d..f40edf2b 100644 --- a/docs/server/configuration.md +++ b/docs/server/configuration.md @@ -1,9 +1,9 @@ # Server configuration `WireframeServer` provides a builder API for adjusting runtime behaviour. The -server employs a typestate to ensure that binding occurs before runtime: -unbound servers do not expose `run` methods. This guide focuses on tuning the -exponential backoff used when accepting connections fails. +server employs a typestate (from `Unbound` to `Bound`) to ensure that binding +occurs before runtime: unbound servers do not expose `run` methods. This guide +focuses on tuning the exponential backoff used when accepting connections fails. ```rust,no_run use wireframe::{app::WireframeApp, server::WireframeServer}; diff --git a/src/server/config/mod.rs b/src/server/config/mod.rs index 19694af3..01e844f5 100644 --- a/src/server/config/mod.rs +++ b/src/server/config/mod.rs @@ -5,10 +5,11 @@ //! TCP binding is provided via the [`binding`](self::binding) module; preamble //! behaviour is customized via the [`preamble`](self::preamble) module. The //! server may be constructed unbound and later bound using -//! [`bind`](WireframeServer::bind) or -//! [`bind_existing_listener`](WireframeServer::bind_existing_listener) on -//! [`Unbound`] servers. The `run` methods are available only once the server -//! is [`Bound`](super::Bound), enforcing at compile time that the binding step +//! [`bind`](super::WireframeServer::bind) or +//! [`bind_existing_listener`](super::WireframeServer::bind_existing_listener) on +//! [`Unbound`](super::Unbound) servers. The `run` methods are available only once +//! the server is [`Bound`](super::Bound), enforcing at compile time that the +//! binding step //! cannot be skipped. use core::marker::PhantomData; diff --git a/src/server/runtime.rs b/src/server/runtime.rs index 491be290..0f469940 100644 --- a/src/server/runtime.rs +++ b/src/server/runtime.rs @@ -129,6 +129,22 @@ where /// # } /// ``` /// + /// Attempting to run a server without binding fails to compile: + /// + /// Binding specifies the network address for the server to listen on. + /// It is required so the server knows where to accept incoming connections. + /// + /// ```compile_fail + /// use wireframe::{app::WireframeApp, server::WireframeServer}; + /// + /// async fn try_run_with_shutdown() { + /// WireframeServer::new(|| WireframeApp::default()) + /// .run_with_shutdown(async {}) + /// .await + /// .expect("unbound servers do not expose run_with_shutdown()"); + /// } + /// ``` + /// /// # Errors /// /// Returns a [`ServerError`] if runtime initialisation fails.