Struct jupiter::commands::Dispatcher
source · pub struct Dispatcher { /* private fields */ }
Expand description
Provides a readonly view of a CommandDictionary used to actually dispatch calls of the appropriate queue.
Being a readonly copy, a dispatch can operate without any locking or synchronization overheads.
Implementations§
source§impl Dispatcher
impl Dispatcher
sourcepub async fn invoke(
&mut self,
request: Request,
connection: Option<&Arc<Connection>>
) -> Result<BytesMut, OutputError>
pub async fn invoke( &mut self, request: Request, connection: Option<&Arc<Connection>> ) -> Result<BytesMut, OutputError>
Actually dispatches the given request to the appropriate queue and returns the result.
The result is either a RESP response already marshalled into a byte buffer or an error. Note that application level errors have already been marshalled into RESP errors like “-CLIENT: ….” or “-SERVER: ….”. These errors which are explicitly reported here always signal that the protocol or IO channel might be inconsistent and therefore that the underlying connection to the client should be terminated.
If this command has been issued via a Connection, a reference to it can be passed in. Otherwise (which is most probably testing), None can be used. This connection is only used by built-in commands (QUIT and CLIENT) as it has to interact with the inner workings of the server.
We could always check for these commands before dispatching, but this would have a direct impact on latency and these commands are rare and not performance critical at all. Therefore we delay checking for them as much as possible.
§Example
// Create a new platform with a commands dictionary and a SYS.COMMANDS command...
let platform = Builder::new()
.enable_server()
.enable_commands()
.enable_core_commands()
.build()
.await;
// Obtain the dispatcher...
let mut dispatcher = platform.require::<CommandDictionary>().dispatcher();
// Create a "SYS.COMMANDS" request...
let request = Request::example(vec!("SYS.COMMANDS"));
// Actually invoke the command via the dispatcher...
let result = dispatcher.invoke(request, None).await;
// We expect to receive a PONG result for our PING command...
assert_eq!(result.is_ok(), true);
// Create a "PING" request...
let request = Request::example(vec!("PING"));
// Actually invoke the command via the dispatcher...
let result = dispatcher.invoke(request, None).await.unwrap();
// We expect to receive a PONG result for our PING command...
assert_eq!(std::str::from_utf8(&result[..]).unwrap(), "+PONG\r\n");
Auto Trait Implementations§
impl Freeze for Dispatcher
impl !RefUnwindSafe for Dispatcher
impl Send for Dispatcher
impl Sync for Dispatcher
impl Unpin for Dispatcher
impl !UnwindSafe for Dispatcher
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more