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 self.process_with(item, |item| self.router.incoming_cpu(item))
109 }
110
111 pub(crate) fn process_with(
116 &self,
117 item: T,
118 cpu: impl FnOnce(&T) -> Option<usize>,
119 ) -> Result<(), T> {
120 if self.shared.status() != ServerStatus::Ready {
121 return Err(item);
122 }
123 let item = match self.router.dispatch_with(item, &self.shared.metrics, cpu) {
124 Ok(()) => return Ok(()),
125 Err(Rejected::Closed(item)) => return Err(item),
127 Err(Rejected::NoWorker(item)) => item,
128 };
129 if let Err(e) = self.cmd.try_send(ServerCommand::Item(item)) {
131 if let ServerCommand::Item(item) = e.into_inner() {
132 Err(item)
133 } else {
134 panic!()
135 }
136 } else {
137 Ok(())
138 }
139 }
140
141 pub fn status(&self) -> ServerStatus {
143 self.shared.status()
144 }
145
146 pub fn status_changed(&self) -> impl Future<Output = ServerStatus> + use<T> {
155 let shared = self.shared.clone();
156 let start = shared.status.load(Ordering::Acquire);
157 async move {
158 loop {
159 let cur = shared.status.load(Ordering::Acquire);
160 if cur != start || status(cur) == ServerStatus::Stopped {
161 return status(cur);
162 }
163 let listener = shared.status_event.listen();
164 let cur = shared.status.load(Ordering::Acquire);
165 if cur != start {
166 return status(cur);
167 }
168 listener.await;
169 }
170 }
171 }
172
173 pub fn pause(&self) -> impl Future<Output = ()> + use<T> {
182 let (tx, rx) = oneshot::channel();
183 let _ = self.cmd.try_send(ServerCommand::Pause(tx));
184 async move {
185 let _ = rx.await;
186 }
187 }
188
189 pub fn resume(&self) -> impl Future<Output = ()> + use<T> {
194 let (tx, rx) = oneshot::channel();
195 let _ = self.cmd.try_send(ServerCommand::Resume(tx));
196 async move {
197 let _ = rx.await;
198 }
199 }
200
201 pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> + use<T> {
210 let (tx, rx) = oneshot::channel();
211 let _ = self.cmd.try_send(ServerCommand::Stop {
212 graceful,
213 completion: Some(tx),
214 });
215 async move {
216 let _ = rx.await;
217 }
218 }
219}
220
221impl<T> Clone for Server<T> {
222 fn clone(&self) -> Self {
223 Self {
224 cmd: self.cmd.clone(),
225 shared: self.shared.clone(),
226 router: self.router.clone(),
227 stop: None,
228 }
229 }
230}
231
232impl<T> Future for Server<T> {
233 type Output = io::Result<()>;
234
235 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
236 let this = self.get_mut();
237
238 if this.stop.is_none() {
239 let (tx, rx) = oneshot::async_channel();
240 if this.cmd.try_send(ServerCommand::NotifyStopped(tx)).is_err() {
241 return Poll::Ready(Ok(()));
242 }
243 this.stop = Some(rx);
244 }
245
246 let _ = ready!(Pin::new(this.stop.as_mut().unwrap()).poll(cx));
247
248 Poll::Ready(Ok(()))
249 }
250}