pub struct ControlServer<H>{ /* private fields */ }Expand description
HTTP server that hosts the control plane router.
Generic over H, which must implement
lightshuttle_runtime::LifecycleHandle. The handle is held inside a
crate::ControlState and shared across all route handlers via axum’s
state mechanism.
§Usage
- Call
bindto open a listener (loopback only, no authentication). - Build a
crate::ControlStatewith the project name and handle. - Construct a
ControlServerviaControlServer::new. - Await
ControlServer::servewith a shutdown future.
For in-process integration tests, use ControlServer::into_router to
get the raw axum router and drive it with tower::ServiceExt::oneshot
without opening a TCP socket.
Implementations§
Source§impl<H> ControlServer<H>
impl<H> ControlServer<H>
Sourcepub fn new(state: ControlState<H>) -> Self
pub fn new(state: ControlState<H>) -> Self
Build a server from the given shared state.
The state holds the project name, the lifecycle handle, and the
Prometheus metrics renderer. It is moved into the axum router when
ControlServer::serve or ControlServer::into_router is called.
Sourcepub fn into_router(self) -> Router
pub fn into_router(self) -> Router
Consume the server and return the underlying axum::Router.
Useful for in-process integration tests: pass the router to
tower::ServiceExt::oneshot to send synthetic requests without the
overhead of a real TCP bind.
Sourcepub async fn serve<F>(self, listener: TcpListener, shutdown: F) -> Result<()>
pub async fn serve<F>(self, listener: TcpListener, shutdown: F) -> Result<()>
Run the control plane on listener until shutdown resolves.
Starts accepting connections immediately. When shutdown resolves,
axum performs a graceful shutdown: it stops accepting new connections
and waits for in-flight requests to complete before returning.
§Errors
Propagates any std::io::Error from the underlying TCP accept loop.
§Example
use std::net::SocketAddr;
use lightshuttle_control::{ControlState, ControlServer, bind};
let addr: SocketAddr = "127.0.0.1:9090".parse().unwrap();
let listener = bind(addr).await?;
let state = ControlState::new("my-project", MyHandle);
let server = ControlServer::new(state);
// Shutdown when Ctrl-C is received.
server
.serve(listener, async { tokio::signal::ctrl_c().await.ok(); })
.awaitAuto Trait Implementations§
impl<H> Freeze for ControlServer<H>where
H: Freeze,
impl<H> RefUnwindSafe for ControlServer<H>where
H: RefUnwindSafe,
impl<H> Send for ControlServer<H>
impl<H> Sync for ControlServer<H>
impl<H> Unpin for ControlServer<H>where
H: Unpin,
impl<H> UnsafeUnpin for ControlServer<H>where
H: UnsafeUnpin,
impl<H> UnwindSafe for ControlServer<H>where
H: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request