1#![allow(clippy::missing_panics_doc)]
2use std::sync::{Arc, atomic::AtomicU64, atomic::Ordering};
3use std::task::{Context, Poll, ready};
4use std::{future::Future, io, pin::Pin};
5
6use async_channel::Sender;
7use event_listener::Event;
8use ntex_rt::signals::Signal;
9
10use crate::manager::{Rejected, Routing, ServerCommand};
11use crate::{ServerStatus, metrics::Metrics};
12
13#[derive(Debug)]
14pub(crate) struct ServerShared {
15 status: AtomicU64,
17 status_event: Event,
18 pub(crate) metrics: Metrics,
19}
20
21impl ServerShared {
22 pub(crate) fn new(metrics: Metrics) -> Self {
23 ServerShared {
24 status: AtomicU64::new(u64::from(ServerStatus::Starting.as_u8())),
25 status_event: Event::new(),
26 metrics,
27 }
28 }
29
30 pub(crate) fn status(&self) -> ServerStatus {
31 status(self.status.load(Ordering::Acquire))
32 }
33
34 pub(crate) fn set_status(&self, st: ServerStatus) {
38 let cur = self.status.load(Ordering::Acquire);
39 if status(cur) != st {
40 let next = ((cur >> 8).wrapping_add(1) << 8) | u64::from(st.as_u8());
41 self.status.store(next, Ordering::Release);
42 self.status_event.notify(usize::MAX);
43 }
44 }
45}
46
47fn status(val: u64) -> ServerStatus {
48 ServerStatus::from_u8(val.to_le_bytes()[0])
49}
50
51#[derive(Debug)]
57pub struct Server<T> {
58 shared: Arc<ServerShared>,
59 router: Arc<Routing<T>>,
60 cmd: Sender<ServerCommand<T>>,
61 stop: Option<oneshot::AsyncReceiver<()>>,
62}
63
64impl Server<crate::net::Connection> {
65 pub fn builder() -> crate::net::ServerBuilder {
67 crate::net::ServerBuilder::default()
68 }
69}
70
71impl<T> Server<T> {
72 pub(crate) fn new(
73 cmd: Sender<ServerCommand<T>>,
74 shared: Arc<ServerShared>,
75 router: Arc<Routing<T>>,
76 ) -> Self {
77 Server {
78 cmd,
79 shared,
80 router,
81 stop: None,
82 }
83 }
84
85 pub(crate) fn metrics_ref(&self) -> &Metrics {
86 &self.shared.metrics
87 }
88
89 pub fn metrics(&self) -> crate::ServerMetrics {
91 self.shared.metrics.snapshot()
92 }
93
94 pub(crate) fn signal(&self, sig: Signal) {
95 let _ = self.cmd.try_send(ServerCommand::Signal(sig));
96 }
97
98 pub fn process(&self, item: T) -> Result<(), T> {
108 if self.shared.status() != ServerStatus::Ready {
109 return Err(item);
110 }
111 let item = match self.router.dispatch(item, &self.shared.metrics) {
112 Ok(()) => return Ok(()),
113 Err(Rejected::Closed(item)) => return Err(item),
115 Err(Rejected::NoWorker(item)) => item,
116 };
117 if let Err(e) = self.cmd.try_send(ServerCommand::Item(item)) {
119 if let ServerCommand::Item(item) = e.into_inner() {
120 Err(item)
121 } else {
122 panic!()
123 }
124 } else {
125 Ok(())
126 }
127 }
128
129 pub fn status(&self) -> ServerStatus {
131 self.shared.status()
132 }
133
134 pub fn status_changed(&self) -> impl Future<Output = ServerStatus> + use<T> {
143 let shared = self.shared.clone();
144 let start = shared.status.load(Ordering::Acquire);
145 async move {
146 loop {
147 let cur = shared.status.load(Ordering::Acquire);
148 if cur != start || status(cur) == ServerStatus::Stopped {
149 return status(cur);
150 }
151 let listener = shared.status_event.listen();
152 let cur = shared.status.load(Ordering::Acquire);
153 if cur != start {
154 return status(cur);
155 }
156 listener.await;
157 }
158 }
159 }
160
161 pub fn pause(&self) -> impl Future<Output = ()> + use<T> {
170 let (tx, rx) = oneshot::channel();
171 let _ = self.cmd.try_send(ServerCommand::Pause(tx));
172 async move {
173 let _ = rx.await;
174 }
175 }
176
177 pub fn resume(&self) -> impl Future<Output = ()> + use<T> {
182 let (tx, rx) = oneshot::channel();
183 let _ = self.cmd.try_send(ServerCommand::Resume(tx));
184 async move {
185 let _ = rx.await;
186 }
187 }
188
189 pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> + use<T> {
198 let (tx, rx) = oneshot::channel();
199 let _ = self.cmd.try_send(ServerCommand::Stop {
200 graceful,
201 completion: Some(tx),
202 });
203 async move {
204 let _ = rx.await;
205 }
206 }
207}
208
209impl<T> Clone for Server<T> {
210 fn clone(&self) -> Self {
211 Self {
212 cmd: self.cmd.clone(),
213 shared: self.shared.clone(),
214 router: self.router.clone(),
215 stop: None,
216 }
217 }
218}
219
220impl<T> Future for Server<T> {
221 type Output = io::Result<()>;
222
223 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
224 let this = self.get_mut();
225
226 if this.stop.is_none() {
227 let (tx, rx) = oneshot::async_channel();
228 if this.cmd.try_send(ServerCommand::NotifyStopped(tx)).is_err() {
229 return Poll::Ready(Ok(()));
230 }
231 this.stop = Some(rx);
232 }
233
234 let _ = ready!(Pin::new(this.stop.as_mut().unwrap()).poll(cx));
235
236 Poll::Ready(Ok(()))
237 }
238}