2020-12-29 00:44:53 +01:00
|
|
|
use std::future::Future;
|
2019-11-14 13:38:24 +01:00
|
|
|
use std::pin::Pin;
|
2018-09-08 18:36:38 +02:00
|
|
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
2018-09-07 22:06:51 +02:00
|
|
|
use std::sync::Arc;
|
2019-11-14 13:38:24 +01:00
|
|
|
use std::task::{Context, Poll};
|
2020-12-29 00:44:53 +01:00
|
|
|
use std::time::Duration;
|
2018-08-19 19:47:04 +02:00
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
use actix_rt::time::{sleep_until, Instant, Sleep};
|
2021-01-29 05:08:14 +01:00
|
|
|
use actix_rt::{spawn, Worker as Arbiter};
|
2019-12-02 17:30:09 +01:00
|
|
|
use actix_utils::counter::Counter;
|
2020-12-29 00:44:53 +01:00
|
|
|
use futures_core::future::LocalBoxFuture;
|
2018-12-06 23:04:42 +01:00
|
|
|
use log::{error, info, trace};
|
2020-12-29 00:44:53 +01:00
|
|
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
|
|
|
use tokio::sync::oneshot;
|
2018-08-19 19:47:04 +02:00
|
|
|
|
2020-12-13 01:46:32 +01:00
|
|
|
use crate::service::{BoxedServerService, InternalServiceFactory};
|
2020-12-29 00:44:53 +01:00
|
|
|
use crate::socket::{MioStream, SocketAddr};
|
|
|
|
use crate::waker_queue::{WakerInterest, WakerQueue};
|
|
|
|
use crate::{join_all, Token};
|
2018-08-19 19:47:04 +02:00
|
|
|
|
2018-11-01 23:33:35 +01:00
|
|
|
pub(crate) struct WorkerCommand(Conn);
|
|
|
|
|
|
|
|
/// Stop worker message. Returns `true` on successful shutdown
|
|
|
|
/// and `false` if some connections still alive.
|
|
|
|
pub(crate) struct StopCommand {
|
|
|
|
graceful: bool,
|
|
|
|
result: oneshot::Sender<bool>,
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
|
|
|
|
2018-12-10 05:30:04 +01:00
|
|
|
#[derive(Debug)]
|
2018-08-19 19:47:04 +02:00
|
|
|
pub(crate) struct Conn {
|
2020-12-29 00:44:53 +01:00
|
|
|
pub io: MioStream,
|
2018-08-19 19:47:04 +02:00
|
|
|
pub token: Token,
|
2019-07-18 13:05:40 +02:00
|
|
|
pub peer: Option<SocketAddr>,
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2018-12-10 07:14:29 +01:00
|
|
|
static MAX_CONNS: AtomicUsize = AtomicUsize::new(25600);
|
2018-09-08 18:36:38 +02:00
|
|
|
|
|
|
|
/// Sets the maximum per-worker number of concurrent connections.
|
|
|
|
///
|
|
|
|
/// All socket listeners will stop accepting connections when this limit is
|
|
|
|
/// reached for each worker.
|
|
|
|
///
|
|
|
|
/// By default max connections is set to a 25k per worker.
|
|
|
|
pub fn max_concurrent_connections(num: usize) {
|
|
|
|
MAX_CONNS.store(num, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
|
|
|
|
thread_local! {
|
2018-09-14 22:07:38 +02:00
|
|
|
static MAX_CONNS_COUNTER: Counter =
|
|
|
|
Counter::new(MAX_CONNS.load(Ordering::Relaxed));
|
2018-09-08 18:36:38 +02:00
|
|
|
}
|
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
pub(crate) fn num_connections() -> usize {
|
|
|
|
MAX_CONNS_COUNTER.with(|conns| conns.total())
|
|
|
|
}
|
|
|
|
|
|
|
|
// a handle to worker that can send message to worker and share the availability of worker to other
|
|
|
|
// thread.
|
2018-08-19 19:47:04 +02:00
|
|
|
#[derive(Clone)]
|
2020-12-29 00:44:53 +01:00
|
|
|
pub(crate) struct WorkerHandle {
|
2018-08-19 19:47:04 +02:00
|
|
|
pub idx: usize,
|
2018-11-01 23:33:35 +01:00
|
|
|
tx1: UnboundedSender<WorkerCommand>,
|
|
|
|
tx2: UnboundedSender<StopCommand>,
|
2018-09-07 22:06:51 +02:00
|
|
|
avail: WorkerAvailability,
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
impl WorkerHandle {
|
2018-09-14 08:46:01 +02:00
|
|
|
pub fn new(
|
2018-10-30 04:29:47 +01:00
|
|
|
idx: usize,
|
2018-11-01 23:33:35 +01:00
|
|
|
tx1: UnboundedSender<WorkerCommand>,
|
|
|
|
tx2: UnboundedSender<StopCommand>,
|
2018-10-30 04:29:47 +01:00
|
|
|
avail: WorkerAvailability,
|
2018-09-14 08:46:01 +02:00
|
|
|
) -> Self {
|
2020-12-29 00:44:53 +01:00
|
|
|
WorkerHandle {
|
2018-11-01 23:33:35 +01:00
|
|
|
idx,
|
|
|
|
tx1,
|
|
|
|
tx2,
|
|
|
|
avail,
|
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2018-09-14 08:46:01 +02:00
|
|
|
pub fn send(&self, msg: Conn) -> Result<(), Conn> {
|
2020-12-29 00:44:53 +01:00
|
|
|
self.tx1.send(WorkerCommand(msg)).map_err(|msg| msg.0 .0)
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn available(&self) -> bool {
|
2018-09-07 22:06:51 +02:00
|
|
|
self.avail.available()
|
|
|
|
}
|
2018-09-14 08:46:01 +02:00
|
|
|
|
2018-09-27 05:40:45 +02:00
|
|
|
pub fn stop(&self, graceful: bool) -> oneshot::Receiver<bool> {
|
2018-11-01 23:33:35 +01:00
|
|
|
let (result, rx) = oneshot::channel();
|
2020-12-29 00:44:53 +01:00
|
|
|
let _ = self.tx2.send(StopCommand { graceful, result });
|
2018-09-14 08:46:01 +02:00
|
|
|
rx
|
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub(crate) struct WorkerAvailability {
|
2020-12-29 00:44:53 +01:00
|
|
|
waker: WakerQueue,
|
2018-09-07 22:06:51 +02:00
|
|
|
available: Arc<AtomicBool>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WorkerAvailability {
|
2020-12-29 00:44:53 +01:00
|
|
|
pub fn new(waker: WakerQueue) -> Self {
|
2018-09-07 22:06:51 +02:00
|
|
|
WorkerAvailability {
|
2020-12-29 00:44:53 +01:00
|
|
|
waker,
|
2018-09-07 22:06:51 +02:00
|
|
|
available: Arc::new(AtomicBool::new(false)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn available(&self) -> bool {
|
|
|
|
self.available.load(Ordering::Acquire)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&self, val: bool) {
|
|
|
|
let old = self.available.swap(val, Ordering::Release);
|
2020-12-29 00:44:53 +01:00
|
|
|
// notify the accept on switched to available.
|
2018-09-07 22:06:51 +02:00
|
|
|
if !old && val {
|
2020-12-29 00:44:53 +01:00
|
|
|
self.waker.wake(WakerInterest::WorkerAvailable);
|
2018-09-07 22:06:51 +02:00
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-29 05:08:14 +01:00
|
|
|
/// Service worker.
|
2018-08-19 19:47:04 +02:00
|
|
|
///
|
2021-01-29 05:08:14 +01:00
|
|
|
/// Worker accepts Socket objects via unbounded channel and starts stream processing.
|
|
|
|
pub(crate) struct ServerWorker {
|
2018-09-14 08:46:01 +02:00
|
|
|
rx: UnboundedReceiver<WorkerCommand>,
|
2018-11-01 23:33:35 +01:00
|
|
|
rx2: UnboundedReceiver<StopCommand>,
|
2019-12-04 10:12:02 +01:00
|
|
|
services: Vec<WorkerService>,
|
2018-09-07 22:06:51 +02:00
|
|
|
availability: WorkerAvailability,
|
2018-09-14 22:07:38 +02:00
|
|
|
conns: Counter,
|
2019-07-18 13:05:40 +02:00
|
|
|
factories: Vec<Box<dyn InternalServiceFactory>>,
|
2018-09-14 08:46:01 +02:00
|
|
|
state: WorkerState,
|
2020-12-29 00:44:53 +01:00
|
|
|
shutdown_timeout: Duration,
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2019-12-04 10:12:02 +01:00
|
|
|
struct WorkerService {
|
|
|
|
factory: usize,
|
|
|
|
status: WorkerServiceStatus,
|
|
|
|
service: BoxedServerService,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WorkerService {
|
|
|
|
fn created(&mut self, service: BoxedServerService) {
|
|
|
|
self.service = service;
|
|
|
|
self.status = WorkerServiceStatus::Unavailable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
enum WorkerServiceStatus {
|
|
|
|
Available,
|
|
|
|
Unavailable,
|
|
|
|
Failed,
|
|
|
|
Restarting,
|
|
|
|
Stopping,
|
|
|
|
Stopped,
|
|
|
|
}
|
|
|
|
|
2021-01-29 05:08:14 +01:00
|
|
|
impl ServerWorker {
|
2018-09-14 08:46:01 +02:00
|
|
|
pub(crate) fn start(
|
2019-12-05 11:40:24 +01:00
|
|
|
idx: usize,
|
2019-07-18 13:05:40 +02:00
|
|
|
factories: Vec<Box<dyn InternalServiceFactory>>,
|
2018-10-30 04:29:47 +01:00
|
|
|
availability: WorkerAvailability,
|
2020-12-29 00:44:53 +01:00
|
|
|
shutdown_timeout: Duration,
|
|
|
|
) -> WorkerHandle {
|
|
|
|
let (tx1, rx) = unbounded_channel();
|
|
|
|
let (tx2, rx2) = unbounded_channel();
|
2019-12-05 11:40:24 +01:00
|
|
|
let avail = availability.clone();
|
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
// every worker runs in it's own arbiter.
|
2021-01-29 03:21:06 +01:00
|
|
|
Arbiter::new().spawn(Box::pin(async move {
|
2020-12-29 00:44:53 +01:00
|
|
|
availability.set(false);
|
2021-01-29 05:08:14 +01:00
|
|
|
let mut wrk = MAX_CONNS_COUNTER.with(move |conns| ServerWorker {
|
2020-12-29 00:44:53 +01:00
|
|
|
rx,
|
|
|
|
rx2,
|
|
|
|
availability,
|
|
|
|
factories,
|
|
|
|
shutdown_timeout,
|
|
|
|
services: Vec::new(),
|
|
|
|
conns: conns.clone(),
|
|
|
|
state: WorkerState::Unavailable,
|
|
|
|
});
|
2019-11-14 13:38:24 +01:00
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
let fut = wrk
|
|
|
|
.factories
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(idx, factory)| {
|
|
|
|
let fut = factory.create();
|
|
|
|
async move {
|
|
|
|
fut.await.map(|r| {
|
|
|
|
r.into_iter().map(|(t, s)| (idx, t, s)).collect::<Vec<_>>()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
spawn(async move {
|
|
|
|
let res: Result<Vec<_>, _> = join_all(fut).await.into_iter().collect();
|
|
|
|
match res {
|
|
|
|
Ok(services) => {
|
|
|
|
for item in services {
|
|
|
|
for (factory, token, service) in item {
|
|
|
|
assert_eq!(token.0, wrk.services.len());
|
|
|
|
wrk.services.push(WorkerService {
|
|
|
|
factory,
|
|
|
|
service,
|
|
|
|
status: WorkerServiceStatus::Unavailable,
|
|
|
|
});
|
2019-12-05 11:40:24 +01:00
|
|
|
}
|
|
|
|
}
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
Err(e) => {
|
|
|
|
error!("Can not start worker: {:?}", e);
|
|
|
|
Arbiter::current().stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wrk.await
|
|
|
|
});
|
|
|
|
}));
|
2019-12-05 11:40:24 +01:00
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
WorkerHandle::new(idx, tx1, tx2, avail)
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2018-09-07 22:06:51 +02:00
|
|
|
fn shutdown(&mut self, force: bool) {
|
|
|
|
if force {
|
2019-12-04 10:12:02 +01:00
|
|
|
self.services.iter_mut().for_each(|srv| {
|
|
|
|
if srv.status == WorkerServiceStatus::Available {
|
|
|
|
srv.status = WorkerServiceStatus::Stopped;
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
});
|
|
|
|
} else {
|
2019-12-04 10:12:02 +01:00
|
|
|
self.services.iter_mut().for_each(move |srv| {
|
|
|
|
if srv.status == WorkerServiceStatus::Available {
|
|
|
|
srv.status = WorkerServiceStatus::Stopping;
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
});
|
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2019-12-04 10:12:02 +01:00
|
|
|
fn check_readiness(&mut self, cx: &mut Context<'_>) -> Result<bool, (Token, usize)> {
|
2019-11-14 13:38:24 +01:00
|
|
|
let mut ready = self.conns.available(cx);
|
2018-09-14 08:46:01 +02:00
|
|
|
let mut failed = None;
|
2020-12-29 00:44:53 +01:00
|
|
|
for (idx, srv) in self.services.iter_mut().enumerate() {
|
2019-12-04 10:12:02 +01:00
|
|
|
if srv.status == WorkerServiceStatus::Available
|
|
|
|
|| srv.status == WorkerServiceStatus::Unavailable
|
|
|
|
{
|
|
|
|
match srv.service.poll_ready(cx) {
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Ready(Ok(_)) => {
|
2019-12-04 10:12:02 +01:00
|
|
|
if srv.status == WorkerServiceStatus::Unavailable {
|
2018-11-03 17:09:14 +01:00
|
|
|
trace!(
|
|
|
|
"Service {:?} is available",
|
2019-12-04 10:12:02 +01:00
|
|
|
self.factories[srv.factory].name(Token(idx))
|
2018-11-03 17:09:14 +01:00
|
|
|
);
|
2019-12-04 10:12:02 +01:00
|
|
|
srv.status = WorkerServiceStatus::Available;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Poll::Pending => {
|
|
|
|
ready = false;
|
|
|
|
|
|
|
|
if srv.status == WorkerServiceStatus::Available {
|
|
|
|
trace!(
|
|
|
|
"Service {:?} is unavailable",
|
|
|
|
self.factories[srv.factory].name(Token(idx))
|
|
|
|
);
|
|
|
|
srv.status = WorkerServiceStatus::Unavailable;
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Ready(Err(_)) => {
|
2018-11-03 17:09:14 +01:00
|
|
|
error!(
|
|
|
|
"Service {:?} readiness check returned error, restarting",
|
2019-12-04 10:12:02 +01:00
|
|
|
self.factories[srv.factory].name(Token(idx))
|
2018-11-03 17:09:14 +01:00
|
|
|
);
|
2019-12-04 10:12:02 +01:00
|
|
|
failed = Some((Token(idx), srv.factory));
|
|
|
|
srv.status = WorkerServiceStatus::Failed;
|
2018-09-18 05:19:48 +02:00
|
|
|
}
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
2018-08-21 07:21:23 +02:00
|
|
|
}
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
|
|
|
if let Some(idx) = failed {
|
|
|
|
Err(idx)
|
2018-08-21 07:21:23 +02:00
|
|
|
} else {
|
2018-09-14 08:46:01 +02:00
|
|
|
Ok(ready)
|
2018-08-21 07:21:23 +02:00
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
|
2018-09-14 08:46:01 +02:00
|
|
|
enum WorkerState {
|
|
|
|
Available,
|
2020-12-29 00:44:53 +01:00
|
|
|
Unavailable,
|
2018-11-03 17:09:14 +01:00
|
|
|
Restarting(
|
|
|
|
usize,
|
|
|
|
Token,
|
2020-12-29 00:44:53 +01:00
|
|
|
LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>>,
|
2018-11-03 17:09:14 +01:00
|
|
|
),
|
2019-12-04 10:12:02 +01:00
|
|
|
Shutdown(
|
2020-12-29 00:44:53 +01:00
|
|
|
Pin<Box<Sleep>>,
|
|
|
|
Pin<Box<Sleep>>,
|
2019-12-04 10:12:02 +01:00
|
|
|
Option<oneshot::Sender<bool>>,
|
|
|
|
),
|
2018-09-12 17:25:14 +02:00
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
|
2021-01-29 05:08:14 +01:00
|
|
|
impl Future for ServerWorker {
|
2019-11-14 13:38:24 +01:00
|
|
|
type Output = ();
|
2018-09-14 08:46:01 +02:00
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
2018-11-01 23:33:35 +01:00
|
|
|
// `StopWorker` message handler
|
2019-11-14 13:38:24 +01:00
|
|
|
if let Poll::Ready(Some(StopCommand { graceful, result })) =
|
2020-12-29 00:44:53 +01:00
|
|
|
Pin::new(&mut self.rx2).poll_recv(cx)
|
2019-11-14 13:38:24 +01:00
|
|
|
{
|
2018-12-06 23:04:42 +01:00
|
|
|
self.availability.set(false);
|
|
|
|
let num = num_connections();
|
|
|
|
if num == 0 {
|
|
|
|
info!("Shutting down worker, 0 connections");
|
|
|
|
let _ = result.send(true);
|
2019-11-14 13:38:24 +01:00
|
|
|
return Poll::Ready(());
|
2018-12-06 23:04:42 +01:00
|
|
|
} else if graceful {
|
|
|
|
self.shutdown(false);
|
2018-11-01 23:33:35 +01:00
|
|
|
let num = num_connections();
|
2018-12-06 23:04:42 +01:00
|
|
|
if num != 0 {
|
|
|
|
info!("Graceful worker shutdown, {} connections", num);
|
|
|
|
self.state = WorkerState::Shutdown(
|
2020-12-29 00:44:53 +01:00
|
|
|
Box::pin(sleep_until(Instant::now() + Duration::from_secs(1))),
|
|
|
|
Box::pin(sleep_until(Instant::now() + self.shutdown_timeout)),
|
2019-12-04 10:12:02 +01:00
|
|
|
Some(result),
|
2018-12-06 23:04:42 +01:00
|
|
|
);
|
2018-11-01 23:33:35 +01:00
|
|
|
} else {
|
2018-12-06 23:04:42 +01:00
|
|
|
let _ = result.send(true);
|
2019-11-14 13:38:24 +01:00
|
|
|
return Poll::Ready(());
|
2018-11-01 23:33:35 +01:00
|
|
|
}
|
2018-12-06 23:04:42 +01:00
|
|
|
} else {
|
|
|
|
info!("Force shutdown worker, {} connections", num);
|
|
|
|
self.shutdown(true);
|
|
|
|
let _ = result.send(false);
|
2019-11-14 13:38:24 +01:00
|
|
|
return Poll::Ready(());
|
2018-11-01 23:33:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-04 10:12:02 +01:00
|
|
|
match self.state {
|
2020-12-29 00:44:53 +01:00
|
|
|
WorkerState::Unavailable => match self.check_readiness(cx) {
|
|
|
|
Ok(true) => {
|
|
|
|
self.state = WorkerState::Available;
|
|
|
|
self.availability.set(true);
|
|
|
|
self.poll(cx)
|
2018-09-12 17:25:14 +02:00
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
Ok(false) => Poll::Pending,
|
|
|
|
Err((token, idx)) => {
|
|
|
|
trace!(
|
|
|
|
"Service {:?} failed, restarting",
|
|
|
|
self.factories[idx].name(token)
|
|
|
|
);
|
|
|
|
self.services[token.0].status = WorkerServiceStatus::Restarting;
|
|
|
|
self.state =
|
|
|
|
WorkerState::Restarting(idx, token, self.factories[idx].create());
|
|
|
|
self.poll(cx)
|
|
|
|
}
|
|
|
|
},
|
2019-12-04 10:12:02 +01:00
|
|
|
WorkerState::Restarting(idx, token, ref mut fut) => {
|
2020-12-29 00:44:53 +01:00
|
|
|
match fut.as_mut().poll(cx) {
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Ready(Ok(item)) => {
|
2020-12-29 00:44:53 +01:00
|
|
|
// only interest in the first item?
|
|
|
|
if let Some((token, service)) = item.into_iter().next() {
|
2018-11-03 17:09:14 +01:00
|
|
|
trace!(
|
|
|
|
"Service {:?} has been restarted",
|
|
|
|
self.factories[idx].name(token)
|
|
|
|
);
|
2019-12-04 10:12:02 +01:00
|
|
|
self.services[token.0].created(service);
|
2020-12-29 00:44:53 +01:00
|
|
|
self.state = WorkerState::Unavailable;
|
2019-12-04 10:12:02 +01:00
|
|
|
return self.poll(cx);
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Ready(Err(_)) => {
|
2018-11-03 17:09:14 +01:00
|
|
|
panic!(
|
|
|
|
"Can not restart {:?} service",
|
|
|
|
self.factories[idx].name(token)
|
|
|
|
);
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
Poll::Pending => return Poll::Pending,
|
2018-09-12 17:25:14 +02:00
|
|
|
}
|
2019-12-02 17:30:09 +01:00
|
|
|
self.poll(cx)
|
2018-09-12 17:25:14 +02:00
|
|
|
}
|
2019-12-04 10:12:02 +01:00
|
|
|
WorkerState::Shutdown(ref mut t1, ref mut t2, ref mut tx) => {
|
2018-09-14 08:46:01 +02:00
|
|
|
let num = num_connections();
|
|
|
|
if num == 0 {
|
2019-12-04 10:12:02 +01:00
|
|
|
let _ = tx.take().unwrap().send(true);
|
2018-12-10 05:30:04 +01:00
|
|
|
Arbiter::current().stop();
|
2019-11-14 13:38:24 +01:00
|
|
|
return Poll::Ready(());
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
2018-09-12 17:25:14 +02:00
|
|
|
|
2018-09-14 08:46:01 +02:00
|
|
|
// check graceful timeout
|
2020-12-29 00:44:53 +01:00
|
|
|
if Pin::new(t2).poll(cx).is_ready() {
|
|
|
|
let _ = tx.take().unwrap().send(false);
|
|
|
|
self.shutdown(true);
|
|
|
|
Arbiter::current().stop();
|
|
|
|
return Poll::Ready(());
|
2018-09-08 18:36:38 +02:00
|
|
|
}
|
2018-09-14 08:46:01 +02:00
|
|
|
|
|
|
|
// sleep for 1 second and then check again
|
2020-12-29 00:44:53 +01:00
|
|
|
if t1.as_mut().poll(cx).is_ready() {
|
|
|
|
*t1 = Box::pin(sleep_until(Instant::now() + Duration::from_secs(1)));
|
|
|
|
let _ = t1.as_mut().poll(cx);
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
|
2019-12-02 17:30:09 +01:00
|
|
|
Poll::Pending
|
2018-09-07 22:06:51 +02:00
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
// actively poll stream and handle worker command
|
|
|
|
WorkerState::Available => loop {
|
|
|
|
match self.check_readiness(cx) {
|
|
|
|
Ok(true) => (),
|
|
|
|
Ok(false) => {
|
|
|
|
trace!("Worker is unavailable");
|
|
|
|
self.availability.set(false);
|
|
|
|
self.state = WorkerState::Unavailable;
|
|
|
|
return self.poll(cx);
|
|
|
|
}
|
|
|
|
Err((token, idx)) => {
|
|
|
|
trace!(
|
|
|
|
"Service {:?} failed, restarting",
|
|
|
|
self.factories[idx].name(token)
|
|
|
|
);
|
|
|
|
self.availability.set(false);
|
|
|
|
self.services[token.0].status = WorkerServiceStatus::Restarting;
|
|
|
|
self.state =
|
|
|
|
WorkerState::Restarting(idx, token, self.factories[idx].create());
|
|
|
|
return self.poll(cx);
|
2018-09-14 08:46:01 +02:00
|
|
|
}
|
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
|
|
|
|
match Pin::new(&mut self.rx).poll_recv(cx) {
|
|
|
|
// handle incoming io stream
|
|
|
|
Poll::Ready(Some(WorkerCommand(msg))) => {
|
|
|
|
let guard = self.conns.get();
|
|
|
|
let _ = self.services[msg.token.0]
|
|
|
|
.service
|
|
|
|
.call((Some(guard), msg.io));
|
|
|
|
}
|
|
|
|
Poll::Pending => return Poll::Pending,
|
|
|
|
Poll::Ready(None) => return Poll::Ready(()),
|
|
|
|
};
|
|
|
|
},
|
2019-12-02 17:30:09 +01:00
|
|
|
}
|
2018-09-07 22:06:51 +02:00
|
|
|
}
|
|
|
|
}
|