mirror of
https://github.com/fafhrd91/actix-net
synced 2025-02-17 14:43:31 +01:00
prepare actix-server release 2.0.0-beta.6
This commit is contained in:
parent
9fa8d7fc5a
commit
ca435b2575
@ -1,13 +1,15 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
* Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to this change. [#349]
|
|
||||||
* Remove `ServerBuilder::configure` [#349]
|
|
||||||
|
## 2.0.0-beta.6 - 2021-10-11
|
||||||
* Add `io-uring` feature for enabling async file I/O on linux. [#374]
|
* Add `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||||
* Server no long listens to SIGHUP signal.
|
* Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block
|
||||||
It actually did not take any action when receiving SIGHUP, the only thing SIGHUP did was to stop
|
subsequent exit signals from working. [#389]
|
||||||
the Server from receiving any future signal, because the `Signals` future stops on the first
|
* Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to
|
||||||
signal received [#389]
|
this change. [#349]
|
||||||
|
* Remove `ServerBuilder::configure` [#349]
|
||||||
|
|
||||||
[#374]: https://github.com/actix/actix-net/pull/374
|
[#374]: https://github.com/actix/actix-net/pull/374
|
||||||
[#349]: https://github.com/actix/actix-net/pull/349
|
[#349]: https://github.com/actix/actix-net/pull/349
|
||||||
@ -15,9 +17,9 @@
|
|||||||
|
|
||||||
|
|
||||||
## 2.0.0-beta.5 - 2021-04-20
|
## 2.0.0-beta.5 - 2021-04-20
|
||||||
* Server shutdown would notify all workers to exit regardless if shutdown is graceful.
|
* Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all
|
||||||
This would make all worker shutdown immediately in force shutdown case. [#333]
|
workers to shutdown immediately in force shutdown case. [#333]
|
||||||
|
|
||||||
[#333]: https://github.com/actix/actix-net/pull/333
|
[#333]: https://github.com/actix/actix-net/pull/333
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-server"
|
name = "actix-server"
|
||||||
version = "2.0.0-beta.5"
|
version = "2.0.0-beta.6"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"fakeshadow <24548779@qq.com>",
|
"fakeshadow <24548779@qq.com>",
|
||||||
|
@ -312,23 +312,25 @@ impl ServerBuilder {
|
|||||||
// Handle `SIGINT`, `SIGTERM`, `SIGQUIT` signals and stop actix system
|
// Handle `SIGINT`, `SIGTERM`, `SIGQUIT` signals and stop actix system
|
||||||
match sig {
|
match sig {
|
||||||
Signal::Int => {
|
Signal::Int => {
|
||||||
info!("SIGINT received, exiting");
|
info!("SIGINT received, starting forced shutdown");
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
self.handle_cmd(ServerCommand::Stop {
|
self.handle_cmd(ServerCommand::Stop {
|
||||||
graceful: false,
|
graceful: false,
|
||||||
completion: None,
|
completion: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal::Term => {
|
Signal::Term => {
|
||||||
info!("SIGTERM received, stopping");
|
info!("SIGTERM received, starting graceful shutdown");
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
self.handle_cmd(ServerCommand::Stop {
|
self.handle_cmd(ServerCommand::Stop {
|
||||||
graceful: true,
|
graceful: true,
|
||||||
completion: None,
|
completion: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal::Quit => {
|
Signal::Quit => {
|
||||||
info!("SIGQUIT received, exiting");
|
info!("SIGQUIT received, starting forced shutdown");
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
self.handle_cmd(ServerCommand::Stop {
|
self.handle_cmd(ServerCommand::Stop {
|
||||||
graceful: false,
|
graceful: false,
|
||||||
@ -359,12 +361,14 @@ impl ServerBuilder {
|
|||||||
|
|
||||||
rt::spawn(async move {
|
rt::spawn(async move {
|
||||||
if graceful {
|
if graceful {
|
||||||
|
// wait for all workers to shut down
|
||||||
let _ = join_all(stop).await;
|
let _ = join_all(stop).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tx) = completion {
|
if let Some(tx) = completion {
|
||||||
let _ = tx.send(());
|
let _ = tx.send(());
|
||||||
}
|
}
|
||||||
|
|
||||||
for tx in notify {
|
for tx in notify {
|
||||||
let _ = tx.send(());
|
let _ = tx.send(());
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ pub(crate) enum ServerCommand {
|
|||||||
Pause(oneshot::Sender<()>),
|
Pause(oneshot::Sender<()>),
|
||||||
Resume(oneshot::Sender<()>),
|
Resume(oneshot::Sender<()>),
|
||||||
Signal(Signal),
|
Signal(Signal),
|
||||||
/// Whether to try and shut down gracefully
|
|
||||||
Stop {
|
Stop {
|
||||||
|
/// True if shut down should be graceful.
|
||||||
graceful: bool,
|
graceful: bool,
|
||||||
completion: Option<oneshot::Sender<()>>,
|
completion: Option<oneshot::Sender<()>>,
|
||||||
},
|
},
|
||||||
@ -24,6 +24,13 @@ pub(crate) enum ServerCommand {
|
|||||||
Notify(oneshot::Sender<()>),
|
Notify(oneshot::Sender<()>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Server handle.
|
||||||
|
///
|
||||||
|
/// # Shutdown Signals
|
||||||
|
/// On UNIX systems, `SIGQUIT` will start a graceful shutdown and `SIGTERM` or `SIGINT` will start a
|
||||||
|
/// forced shutdown. On Windows, a CTRL-C signal will start a forced shutdown.
|
||||||
|
///
|
||||||
|
/// A graceful shutdown will wait for all workers to stop first.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Server(
|
pub struct Server(
|
||||||
UnboundedSender<ServerCommand>,
|
UnboundedSender<ServerCommand>,
|
||||||
|
@ -4,27 +4,33 @@ use std::task::{Context, Poll};
|
|||||||
|
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
|
|
||||||
/// Different types of process signals
|
/// Types of process signals.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
pub(crate) enum Signal {
|
pub(crate) enum Signal {
|
||||||
/// SIGINT
|
/// `SIGINT`
|
||||||
Int,
|
Int,
|
||||||
/// SIGTERM
|
|
||||||
|
/// `SIGTERM`
|
||||||
Term,
|
Term,
|
||||||
/// SIGQUIT
|
|
||||||
|
/// `SIGQUIT`
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Process signal listener.
|
||||||
pub(crate) struct Signals {
|
pub(crate) struct Signals {
|
||||||
srv: Server,
|
srv: Server,
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
signals: futures_core::future::LocalBoxFuture<'static, std::io::Result<()>>,
|
signals: futures_core::future::LocalBoxFuture<'static, std::io::Result<()>>,
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
signals: Vec<(Signal, actix_rt::signal::unix::Signal)>,
|
signals: Vec<(Signal, actix_rt::signal::unix::Signal)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signals {
|
impl Signals {
|
||||||
|
/// Spawns a signal listening future that is able to send commands to the `Server`.
|
||||||
pub(crate) fn start(srv: Server) {
|
pub(crate) fn start(srv: Server) {
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
{
|
{
|
||||||
@ -33,6 +39,7 @@ impl Signals {
|
|||||||
signals: Box::pin(actix_rt::signal::ctrl_c()),
|
signals: Box::pin(actix_rt::signal::ctrl_c()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
use actix_rt::signal::unix;
|
use actix_rt::signal::unix;
|
||||||
@ -76,6 +83,7 @@ impl Future for Signals {
|
|||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
for (sig, fut) in self.signals.iter_mut() {
|
for (sig, fut) in self.signals.iter_mut() {
|
||||||
|
@ -5,13 +5,12 @@ use actix_rt::{net::TcpStream, System};
|
|||||||
|
|
||||||
use crate::{Server, ServerBuilder, ServiceFactory};
|
use crate::{Server, ServerBuilder, ServiceFactory};
|
||||||
|
|
||||||
/// The `TestServer` type.
|
/// A testing server.
|
||||||
///
|
///
|
||||||
/// `TestServer` is very simple test server that simplify process of writing
|
/// `TestServer` is very simple test server that simplify process of writing integration tests for
|
||||||
/// integration tests for actix-net applications.
|
/// network applications.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_service::fn_service;
|
/// use actix_service::fn_service;
|
||||||
/// use actix_server::TestServer;
|
/// use actix_server::TestServer;
|
||||||
@ -39,7 +38,7 @@ pub struct TestServerRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestServer {
|
impl TestServer {
|
||||||
/// Start new server with server builder
|
/// Start new server with server builder.
|
||||||
pub fn start<F>(mut factory: F) -> TestServerRuntime
|
pub fn start<F>(mut factory: F) -> TestServerRuntime
|
||||||
where
|
where
|
||||||
F: FnMut(ServerBuilder) -> ServerBuilder + Send + 'static,
|
F: FnMut(ServerBuilder) -> ServerBuilder + Send + 'static,
|
||||||
@ -64,7 +63,7 @@ impl TestServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start new test server with application factory
|
/// Start new test server with application factory.
|
||||||
pub fn with<F: ServiceFactory<TcpStream>>(factory: F) -> TestServerRuntime {
|
pub fn with<F: ServiceFactory<TcpStream>>(factory: F) -> TestServerRuntime {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
@ -99,7 +98,7 @@ impl TestServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get first available unused local address
|
/// Get first available unused local address.
|
||||||
pub fn unused_addr() -> net::SocketAddr {
|
pub fn unused_addr() -> net::SocketAddr {
|
||||||
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
|
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||||
let socket = mio::net::TcpSocket::new_v4().unwrap();
|
let socket = mio::net::TcpSocket::new_v4().unwrap();
|
||||||
@ -111,27 +110,27 @@ impl TestServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestServerRuntime {
|
impl TestServerRuntime {
|
||||||
/// Test server host
|
/// Test server host.
|
||||||
pub fn host(&self) -> &str {
|
pub fn host(&self) -> &str {
|
||||||
&self.host
|
&self.host
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test server port
|
/// Test server port.
|
||||||
pub fn port(&self) -> u16 {
|
pub fn port(&self) -> u16 {
|
||||||
self.port
|
self.port
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get test server address
|
/// Get test server address.
|
||||||
pub fn addr(&self) -> net::SocketAddr {
|
pub fn addr(&self) -> net::SocketAddr {
|
||||||
self.addr
|
self.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop http server
|
/// Stop server.
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
self.system.stop();
|
self.system.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to server, return tokio TcpStream
|
/// Connect to server, returning a Tokio `TcpStream`.
|
||||||
pub fn connect(&self) -> std::io::Result<TcpStream> {
|
pub fn connect(&self) -> std::io::Result<TcpStream> {
|
||||||
TcpStream::from_std(net::TcpStream::connect(self.addr)?)
|
TcpStream::from_std(net::TcpStream::connect(self.addr)?)
|
||||||
}
|
}
|
||||||
|
@ -429,13 +429,15 @@ struct Restart {
|
|||||||
fut: LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>>,
|
fut: LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown keep states necessary for server shutdown:
|
/// State necessary for server shutdown.
|
||||||
// Sleep for interval check the shutdown progress.
|
|
||||||
// Instant for the start time of shutdown.
|
|
||||||
// Sender for send back the shutdown outcome(force/grace) to StopCommand caller.
|
|
||||||
struct Shutdown {
|
struct Shutdown {
|
||||||
|
// Interval for checking the shutdown progress.
|
||||||
timer: Pin<Box<Sleep>>,
|
timer: Pin<Box<Sleep>>,
|
||||||
|
|
||||||
|
/// Start time of shutdown.
|
||||||
start_from: Instant,
|
start_from: Instant,
|
||||||
|
|
||||||
|
/// Notify of the shutdown outcome (force/grace) to stop caller.
|
||||||
tx: oneshot::Sender<bool>,
|
tx: oneshot::Sender<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,23 +523,25 @@ impl Future for ServerWorker {
|
|||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
WorkerState::Shutdown(ref mut shutdown) => {
|
WorkerState::Shutdown(ref mut shutdown) => {
|
||||||
// Wait for 1 second.
|
// wait for 1 second
|
||||||
ready!(shutdown.timer.as_mut().poll(cx));
|
ready!(shutdown.timer.as_mut().poll(cx));
|
||||||
|
|
||||||
if this.counter.total() == 0 {
|
if this.counter.total() == 0 {
|
||||||
// Graceful shutdown.
|
// graceful shutdown
|
||||||
if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
|
if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
|
||||||
let _ = shutdown.tx.send(true);
|
let _ = shutdown.tx.send(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
} else if shutdown.start_from.elapsed() >= this.shutdown_timeout {
|
} else if shutdown.start_from.elapsed() >= this.shutdown_timeout {
|
||||||
// Timeout forceful shutdown.
|
// timeout forceful shutdown
|
||||||
if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
|
if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
|
||||||
let _ = shutdown.tx.send(false);
|
let _ = shutdown.tx.send(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
// Reset timer and wait for 1 second.
|
// reset timer and wait for 1 second
|
||||||
let time = Instant::now() + Duration::from_secs(1);
|
let time = Instant::now() + Duration::from_secs(1);
|
||||||
shutdown.timer.as_mut().reset(time);
|
shutdown.timer.as_mut().reset(time);
|
||||||
shutdown.timer.as_mut().poll(cx)
|
shutdown.timer.as_mut().poll(cx)
|
||||||
|
@ -64,7 +64,7 @@ tokio-native-tls = { version = "0.3", optional = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2.2.0"
|
actix-rt = "2.2.0"
|
||||||
actix-server = "2.0.0-beta.5"
|
actix-server = "2.0.0-beta.6"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
|
futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user