1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-24 05:52:59 +01:00

refactor server configurations

This commit is contained in:
Nikolay Kim 2019-12-04 21:34:48 +06:00
parent de84663768
commit 21dcc22e53
6 changed files with 111 additions and 44 deletions

View File

@ -6,6 +6,8 @@
* Fix compilation on non-unix platforms * Fix compilation on non-unix platforms
* Better handling server configuration
## [1.0.0-alpha.2] - 2019-12-02 ## [1.0.0-alpha.2] - 2019-12-02

View File

@ -42,3 +42,4 @@ mio-uds = { version = "0.6.7" }
[dev-dependencies] [dev-dependencies]
bytes = "0.4" bytes = "0.4"
env_logger = "0.6" env_logger = "0.6"
actix-testing = "1.0.0-alpha.2"

View File

@ -4,7 +4,7 @@ use std::{fmt, io, net};
use actix_rt::net::TcpStream; use actix_rt::net::TcpStream;
use actix_service as actix; use actix_service as actix;
use actix_utils::counter::CounterGuard; use actix_utils::counter::CounterGuard;
use futures::future::{Future, FutureExt, LocalBoxFuture}; use futures::future::{ok, Future, FutureExt, LocalBoxFuture};
use log::error; use log::error;
use super::builder::bind_addr; use super::builder::bind_addr;
@ -75,7 +75,8 @@ impl ServiceConfig {
pub(super) struct ConfiguredService { pub(super) struct ConfiguredService {
rt: Box<dyn ServiceRuntimeConfiguration>, rt: Box<dyn ServiceRuntimeConfiguration>,
names: HashMap<Token, (String, net::SocketAddr)>, names: HashMap<Token, (String, net::SocketAddr)>,
services: HashMap<String, Token>, topics: HashMap<String, Token>,
services: Vec<Token>,
} }
impl ConfiguredService { impl ConfiguredService {
@ -83,13 +84,15 @@ impl ConfiguredService {
ConfiguredService { ConfiguredService {
rt, rt,
names: HashMap::new(), names: HashMap::new(),
services: HashMap::new(), topics: HashMap::new(),
services: Vec::new(),
} }
} }
pub(super) fn stream(&mut self, token: Token, name: String, addr: net::SocketAddr) { pub(super) fn stream(&mut self, token: Token, name: String, addr: net::SocketAddr) {
self.names.insert(token, (name.clone(), addr)); self.names.insert(token, (name.clone(), addr));
self.services.insert(name, token); self.topics.insert(name.clone(), token);
self.services.push(token);
} }
} }
@ -102,34 +105,50 @@ impl InternalServiceFactory for ConfiguredService {
Box::new(Self { Box::new(Self {
rt: self.rt.clone(), rt: self.rt.clone(),
names: self.names.clone(), names: self.names.clone(),
topics: self.topics.clone(),
services: self.services.clone(), services: self.services.clone(),
}) })
} }
fn create(&self) -> LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>> { fn create(&self) -> LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>> {
// configure services // configure services
let mut rt = ServiceRuntime::new(self.services.clone()); let mut rt = ServiceRuntime::new(self.topics.clone());
self.rt.configure(&mut rt); self.rt.configure(&mut rt);
rt.validate(); rt.validate();
let mut names = self.names.clone();
let tokens = self.services.clone();
// construct services // construct services
async move { async move {
let services = rt.services; let mut services = rt.services;
// TODO: Proper error handling here // TODO: Proper error handling here
for f in rt.onstart.into_iter() { for f in rt.onstart.into_iter() {
f.await; f.await;
} }
let mut res = vec![]; let mut res = vec![];
for (token, ns) in services.into_iter() { for token in tokens {
let newserv = ns.new_service(()); if let Some(srv) = services.remove(&token) {
match newserv.await { let newserv = srv.new_service(());
Ok(serv) => { match newserv.await {
res.push((token, serv)); Ok(serv) => {
} res.push((token, serv));
Err(_) => { }
error!("Can not construct service"); Err(_) => {
return Err(()); error!("Can not construct service");
return Err(());
}
} }
} else {
let name = names.remove(&token).unwrap().0;
res.push((
token,
Box::new(StreamService::new(actix::service_fn2(
move |_: TcpStream| {
error!("Service {:?} is not configured", name);
ok::<_, ()>(())
},
))),
));
}; };
} }
return Ok(res); return Ok(res);

View File

@ -81,12 +81,10 @@ where
if let Ok(stream) = stream { if let Ok(stream) = stream {
let f = self.service.call(stream); let f = self.service.call(stream);
spawn( spawn(async move {
async move { let _ = f.await;
let _ = f.await; drop(guard);
drop(guard); });
}
);
ok(()) ok(())
} else { } else {
err(()) err(())

View File

@ -188,31 +188,29 @@ impl Worker {
})); }));
} }
spawn( spawn(async move {
async move { let res = join_all(fut).await;
let res = join_all(fut).await; let res: Result<Vec<_>, _> = res.into_iter().collect();
let res: Result<Vec<_>, _> = res.into_iter().collect(); match res {
match res { Ok(services) => {
Ok(services) => { for item in services {
for item in services { for (factory, token, service) in item {
for (factory, token, service) in item { assert_eq!(token.0, wrk.services.len());
assert_eq!(token.0, wrk.services.len()); wrk.services.push(WorkerService {
wrk.services.push(WorkerService { factory,
factory, service,
service, status: WorkerServiceStatus::Unavailable,
status: WorkerServiceStatus::Unavailable, });
});
}
} }
} }
Err(e) => {
error!("Can not start worker: {:?}", e);
Arbiter::current().stop();
}
} }
wrk.await Err(e) => {
error!("Can not start worker: {:?}", e);
Arbiter::current().stop();
}
} }
); wrk.await
});
} }
fn shutdown(&mut self, force: bool) { fn shutdown(&mut self, force: bool) {

View File

@ -1,5 +1,6 @@
use std::io::Read; use std::io::Read;
use std::sync::mpsc; use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use std::sync::{mpsc, Arc};
use std::{net, thread, time}; use std::{net, thread, time};
use actix_codec::{BytesCodec, Framed}; use actix_codec::{BytesCodec, Framed};
@ -7,7 +8,8 @@ use actix_rt::net::TcpStream;
use actix_server::Server; use actix_server::Server;
use actix_service::service_fn; use actix_service::service_fn;
use bytes::Bytes; use bytes::Bytes;
use futures::{future::ok, SinkExt}; use futures::future::{lazy, ok};
use futures::SinkExt;
use net2::TcpBuilder; use net2::TcpBuilder;
fn unused_addr() -> net::SocketAddr { fn unused_addr() -> net::SocketAddr {
@ -126,3 +128,50 @@ fn test_start() {
let _ = sys.stop(); let _ = sys.stop();
let _ = h.join(); let _ = h.join();
} }
#[test]
fn test_configure() {
let addr1 = unused_addr();
let addr2 = unused_addr();
let addr3 = unused_addr();
let (tx, rx) = mpsc::channel();
let num = Arc::new(AtomicUsize::new(0));
let num2 = num.clone();
let h = thread::spawn(move || {
let num = num2.clone();
let sys = actix_rt::System::new("test");
let srv = Server::build()
.configure(move |cfg| {
let num = num.clone();
let lst = net::TcpListener::bind(addr3).unwrap();
cfg.bind("addr1", addr1)
.unwrap()
.bind("addr2", addr2)
.unwrap()
.listen("addr3", lst)
.apply(move |rt| {
let num = num.clone();
rt.service("addr1", service_fn(|_| ok::<_, ()>(())));
rt.service("addr3", service_fn(|_| ok::<_, ()>(())));
rt.on_start(lazy(move |_| {
let _ = num.fetch_add(1, Relaxed);
}))
})
})
.unwrap()
.workers(1)
.start();
let _ = tx.send((srv, actix_rt::System::current()));
let _ = sys.run();
});
let (_, sys) = rx.recv().unwrap();
thread::sleep(time::Duration::from_millis(500));
assert!(net::TcpStream::connect(addr1).is_ok());
assert!(net::TcpStream::connect(addr2).is_ok());
assert!(net::TcpStream::connect(addr3).is_ok());
assert_eq!(num.load(Relaxed), 1);
let _ = sys.stop();
let _ = h.join();
}