Eliminated a panic that can occur when using IrcServerFuture, and recommend using IrcReactor instead.
This commit is contained in:
parent
fd4e5706eb
commit
67cca339a7
2 changed files with 33 additions and 20 deletions
|
@ -1,10 +1,10 @@
|
||||||
//! A system for creating and managing IRC server connections.
|
//! A system for creating and managing IRC server connections.
|
||||||
//!
|
//!
|
||||||
//! This API provides the ability to create and manage multiple IRC servers that can run on the same
|
//! This API provides the ability to create and manage multiple IRC servers that can run on the same
|
||||||
//! thread through the use of a shared event loop. It also replaces the old functionality of
|
//! thread through the use of a shared event loop. It can also be used to encapsulate the dependency
|
||||||
//! `IrcServer::new_future` and better encapsulates dependencies on `tokio` and `futures`. Finally,
|
//! on `tokio` and `futures` in the use of `IrcServer::new_future`. This means that knowledge of
|
||||||
//! it provides some escape hatches that let advanced users take advantage of these dependencies
|
//! those libraries should be unnecessary for the average user. Nevertheless, this API also provides
|
||||||
//! regardless.
|
//! some escape hatches that let advanced users take further advantage of these dependencies.
|
||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
|
@ -28,7 +28,7 @@ use futures::future;
|
||||||
use tokio_core::reactor::{Core, Handle};
|
use tokio_core::reactor::{Core, Handle};
|
||||||
|
|
||||||
use client::data::Config;
|
use client::data::Config;
|
||||||
use client::server::{IrcServer, IrcServerFuture, Server};
|
use client::server::{IrcServer, IrcServerFuture, PackedIrcServer, Server};
|
||||||
use error;
|
use error;
|
||||||
use proto::Message;
|
use proto::Message;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl IrcReactor {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn prepare_server<'a>(&mut self, config: &'a Config) -> error::Result<IrcServerFuture<'a>> {
|
pub fn prepare_server<'a>(&mut self, config: &'a Config) -> error::Result<IrcServerFuture<'a>> {
|
||||||
IrcServer::new_future(self.inner.handle(), config)
|
IrcServer::new_future(self.inner_handle(), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs an [IrcServerFuture](./server/struct.IrcServerFuture.html), such as one from
|
/// Runs an [IrcServerFuture](./server/struct.IrcServerFuture.html), such as one from
|
||||||
|
@ -91,7 +91,10 @@ impl IrcReactor {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn connect_server(&mut self, future: IrcServerFuture) -> error::Result<IrcServer> {
|
pub fn connect_server(&mut self, future: IrcServerFuture) -> error::Result<IrcServer> {
|
||||||
self.inner.run(future)
|
self.inner.run(future).map(|PackedIrcServer(server, future)| {
|
||||||
|
self.register_future(future);
|
||||||
|
server
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new IRC server from the specified configuration, connecting immediately. This is
|
/// Creates a new IRC server from the specified configuration, connecting immediately. This is
|
||||||
|
|
|
@ -741,7 +741,9 @@ impl IrcServer {
|
||||||
/// Proper usage requires familiarity with `tokio` and `futures`. You can find more information
|
/// Proper usage requires familiarity with `tokio` and `futures`. You can find more information
|
||||||
/// in the crate documentation for [tokio-core](http://docs.rs/tokio-core) or
|
/// in the crate documentation for [tokio-core](http://docs.rs/tokio-core) or
|
||||||
/// [futures](http://docs.rs/futures). Additionally, you can find detailed tutorials on using
|
/// [futures](http://docs.rs/futures). Additionally, you can find detailed tutorials on using
|
||||||
/// both libraries on the [tokio website](https://tokio.rs/docs/getting-started/tokio/).
|
/// both libraries on the [tokio website](https://tokio.rs/docs/getting-started/tokio/). An easy
|
||||||
|
/// to use abstraction that does not require this knowledge is available via
|
||||||
|
/// [IrcReactors](../reactor/struct.IrcReactor.html).
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
@ -749,6 +751,7 @@ impl IrcServer {
|
||||||
/// # extern crate tokio_core;
|
/// # extern crate tokio_core;
|
||||||
/// # use std::default::Default;
|
/// # use std::default::Default;
|
||||||
/// # use irc::client::prelude::*;
|
/// # use irc::client::prelude::*;
|
||||||
|
/// # use irc::client::server::PackedIrcServer;
|
||||||
/// # use irc::error;
|
/// # use irc::error;
|
||||||
/// # use tokio_core::reactor::Core;
|
/// # use tokio_core::reactor::Core;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
|
@ -760,21 +763,21 @@ impl IrcServer {
|
||||||
/// let mut reactor = Core::new().unwrap();
|
/// let mut reactor = Core::new().unwrap();
|
||||||
/// let future = IrcServer::new_future(reactor.handle(), &config).unwrap();
|
/// let future = IrcServer::new_future(reactor.handle(), &config).unwrap();
|
||||||
/// // immediate connection errors (like no internet) will turn up here...
|
/// // immediate connection errors (like no internet) will turn up here...
|
||||||
/// let server = reactor.run(future).unwrap();
|
/// let PackedIrcServer(server, future) = reactor.run(future).unwrap();
|
||||||
/// // runtime errors (like disconnections and so forth) will turn up here...
|
/// // runtime errors (like disconnections and so forth) will turn up here...
|
||||||
/// reactor.run(server.stream().for_each(move |irc_msg| {
|
/// reactor.run(server.stream().for_each(move |irc_msg| {
|
||||||
/// // processing messages works like usual
|
/// // processing messages works like usual
|
||||||
/// process_msg(&server, irc_msg)
|
/// process_msg(&server, irc_msg)
|
||||||
/// })).unwrap();
|
/// }).join(future)).unwrap();
|
||||||
/// # }
|
/// # }
|
||||||
/// # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
|
/// # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
|
||||||
/// ```
|
/// ```
|
||||||
pub(crate) fn new_future(handle: Handle, config: &Config) -> error::Result<IrcServerFuture> {
|
pub fn new_future(handle: Handle, config: &Config) -> error::Result<IrcServerFuture> {
|
||||||
let (tx_outgoing, rx_outgoing) = mpsc::unbounded();
|
let (tx_outgoing, rx_outgoing) = mpsc::unbounded();
|
||||||
|
|
||||||
Ok(IrcServerFuture {
|
Ok(IrcServerFuture {
|
||||||
conn: Connection::new(config, &handle)?,
|
conn: Connection::new(config, &handle)?,
|
||||||
handle: handle,
|
_handle: handle,
|
||||||
config: config,
|
config: config,
|
||||||
tx_outgoing: Some(tx_outgoing),
|
tx_outgoing: Some(tx_outgoing),
|
||||||
rx_outgoing: Some(rx_outgoing),
|
rx_outgoing: Some(rx_outgoing),
|
||||||
|
@ -800,17 +803,18 @@ impl IrcServer {
|
||||||
/// Interaction with this future relies on the `futures` API, but is only expected for more advanced
|
/// Interaction with this future relies on the `futures` API, but is only expected for more advanced
|
||||||
/// use cases. To learn more, you can view the documentation for the
|
/// use cases. To learn more, you can view the documentation for the
|
||||||
/// [futures](https://docs.rs/futures/) crate, or the tutorials for
|
/// [futures](https://docs.rs/futures/) crate, or the tutorials for
|
||||||
/// [tokio](https://tokio.rs/docs/getting-started/futures/).
|
/// [tokio](https://tokio.rs/docs/getting-started/futures/). An easy to use abstraction that does
|
||||||
|
/// not require this knowledge is available via [IrcReactors](../reactor/struct.IrcReactor.html).
|
||||||
pub struct IrcServerFuture<'a> {
|
pub struct IrcServerFuture<'a> {
|
||||||
conn: ConnectionFuture<'a>,
|
conn: ConnectionFuture<'a>,
|
||||||
handle: Handle,
|
_handle: Handle,
|
||||||
config: &'a Config,
|
config: &'a Config,
|
||||||
tx_outgoing: Option<UnboundedSender<Message>>,
|
tx_outgoing: Option<UnboundedSender<Message>>,
|
||||||
rx_outgoing: Option<UnboundedReceiver<Message>>,
|
rx_outgoing: Option<UnboundedReceiver<Message>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Future for IrcServerFuture<'a> {
|
impl<'a> Future for IrcServerFuture<'a> {
|
||||||
type Item = IrcServer;
|
type Item = PackedIrcServer;
|
||||||
type Error = error::Error;
|
type Error = error::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
|
@ -822,19 +826,25 @@ impl<'a> Future for IrcServerFuture<'a> {
|
||||||
let outgoing_future = sink.send_all(self.rx_outgoing.take().unwrap().map_err(|()| {
|
let outgoing_future = sink.send_all(self.rx_outgoing.take().unwrap().map_err(|()| {
|
||||||
let res: error::Error = error::ErrorKind::ChannelError.into();
|
let res: error::Error = error::ErrorKind::ChannelError.into();
|
||||||
res
|
res
|
||||||
})).map(|_| ()).map_err(|e| panic!(e));
|
})).map(|_| ());
|
||||||
|
|
||||||
self.handle.spawn(outgoing_future);
|
let server = IrcServer {
|
||||||
|
|
||||||
Ok(Async::Ready(IrcServer {
|
|
||||||
state: Arc::new(ServerState::new(
|
state: Arc::new(ServerState::new(
|
||||||
stream, self.tx_outgoing.take().unwrap(), self.config.clone()
|
stream, self.tx_outgoing.take().unwrap(), self.config.clone()
|
||||||
)),
|
)),
|
||||||
view: view,
|
view: view,
|
||||||
}))
|
};
|
||||||
|
Ok(Async::Ready(PackedIrcServer(server, Box::new(outgoing_future))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An `IrcServer` packaged with a future that drives its message sending. In order for the server
|
||||||
|
/// to actually work properly, this future _must_ be running.
|
||||||
|
///
|
||||||
|
/// This type should only be used by advanced users who are familiar with the implementation of this
|
||||||
|
/// crate. An easy to use abstraction that does not require this knowledge is available via
|
||||||
|
/// [IrcReactors](../reactor/struct.IrcReactor.html).
|
||||||
|
pub struct PackedIrcServer(pub IrcServer, pub Box<Future<Item = (), Error = error::Error>>);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
Loading…
Add table
Reference in a new issue