Browse Source

Introduce generic EventHandler trait.

main
Titouan Rigoudy 2 years ago
parent
commit
68161b2f8b
5 changed files with 61 additions and 45 deletions
  1. +2
    -2
      client/src/control/listener.rs
  2. +3
    -23
      client/src/dispatcher.rs
  3. +40
    -0
      client/src/event.rs
  4. +3
    -2
      client/src/main.rs
  5. +13
    -18
      client/src/room/event.rs

+ 2
- 2
client/src/control/listener.rs View File

@ -13,7 +13,7 @@ use tokio_tungstenite::WebSocketStream;
use crate::control::request::*;
use crate::control::response::*;
use crate::dispatcher::Message;
use crate::event::Message;
async fn forward_incoming(
mut incoming: SplitStream<WebSocketStream<TcpStream>>,
@ -185,7 +185,7 @@ mod tests {
use tokio_tungstenite::tungstenite::Message as WebSocketMessage;
use crate::control::{Request, Response, RoomLeaveResponse};
use crate::dispatcher::Message;
use crate::event::Message;
// A bound `Listener` packaged with the channels it needs to run.
// Convenient for tests.


+ 3
- 23
client/src/dispatcher.rs View File

@ -1,38 +1,18 @@
//! This module defines the central message dispatcher to the client process.
use std::fmt::Debug;
use log::{error, warn};
use solstice_proto::server::ServerResponse;
use crate::context::Context;
use crate::control::Request as ControlRequest;
use crate::event::{Message, EventHandler};
use crate::handlers::*;
use crate::message_handler::MessageHandler;
use crate::room::{HandleRoomEvent, RoomEvent, RoomEventHandler};
/// The type of messages dispatched by a dispatcher.
#[derive(Debug, Eq, PartialEq)]
pub enum Message {
ControlRequest(ControlRequest),
ServerResponse(ServerResponse),
}
impl From<ServerResponse> for Message {
fn from(response: ServerResponse) -> Self {
Self::ServerResponse(response)
}
}
impl From<ControlRequest> for Message {
fn from(request: ControlRequest) -> Self {
Self::ControlRequest(request)
}
}
use crate::room::{RoomEvent, RoomEventHandler};
/// Subsystem event handlers to which the `Dispatcher` dispatches events.
pub trait DispatcherHandlers {
type RoomEventHandler: HandleRoomEvent;
type RoomEventHandler: EventHandler<Event=RoomEvent>;
fn room_event_handler(&mut self) -> &mut Self::RoomEventHandler;
}


+ 40
- 0
client/src/event.rs View File

@ -0,0 +1,40 @@
//! Defines the root event model for the client application.
use solstice_proto::ServerResponse;
use crate::context::Context;
use crate::control;
// TODO: Rename to `Event`.
/// The type of messages dispatched by a dispatcher.
#[derive(Debug, Eq, PartialEq)]
pub enum Message {
ControlRequest(control::Request),
ServerResponse(ServerResponse),
}
impl From<ServerResponse> for Message {
fn from(response: ServerResponse) -> Self {
Self::ServerResponse(response)
}
}
impl From<control::Request> for Message {
fn from(request: control::Request) -> Self {
Self::ControlRequest(request)
}
}
/// An interface for event handlers.
///
/// Allows mocking of handlers in tests.
pub trait EventHandler {
type Event;
/// Handles the given `event` against the given global `context`.
fn handle(
&mut self,
context: &mut Context,
event: Self::Event,
) -> anyhow::Result<()>;
}

+ 3
- 2
client/src/main.rs View File

@ -13,6 +13,7 @@ mod config;
mod context;
mod control;
mod dispatcher;
mod event;
mod handlers;
mod login;
mod message_handler;
@ -43,7 +44,7 @@ fn old_main(config: Config) {
async fn run_client(
config: Config,
request_rx: mpsc::Receiver<ServerRequest>,
dispatcher_tx: mpsc::Sender<dispatcher::Message>,
dispatcher_tx: mpsc::Sender<event::Message>,
) -> anyhow::Result<()> {
info!("Connecting to server at {}.", config.server_address);
let stream = TcpStream::connect(&config.server_address)
@ -62,7 +63,7 @@ async fn run_client(
let forwarder_task = tokio::spawn(async move {
while let Some(response) = response_rx.recv().await {
dispatcher_tx
.send(dispatcher::Message::ServerResponse(response))
.send(event::Message::ServerResponse(response))
.await
.expect("dispatcher channel closed");
}


+ 13
- 18
client/src/room/event.rs View File

@ -7,6 +7,7 @@ use solstice_proto::ServerRequest;
use crate::context::Context;
use crate::control;
use crate::event::EventHandler;
use crate::room::RoomMessage;
/// An event affecting the chat room module.
@ -20,19 +21,7 @@ pub enum RoomEvent {
MessageResponse(server::RoomMessageResponse),
}
/// An interface for room event handlers.
///
/// Allows mocking of handlers in tests.
pub trait HandleRoomEvent {
/// Handles the given `event` against the given global `context`.
fn handle(
&mut self,
context: &mut Context,
event: RoomEvent,
) -> anyhow::Result<()>;
}
/// The real, default implementation of `HandleRoomEvent`.
/// The real, default room event handler.
#[derive(Default)]
pub struct RoomEventHandler;
@ -168,7 +157,9 @@ fn handle_message_response(
.context("sending control response")
}
impl HandleRoomEvent for RoomEventHandler {
impl EventHandler for RoomEventHandler {
type Event = RoomEvent;
fn handle(
&mut self,
context: &mut Context,
@ -199,19 +190,22 @@ impl HandleRoomEvent for RoomEventHandler {
#[cfg(test)]
pub mod testing {
use crate::context::Context;
use crate::event::EventHandler;
use super::{HandleRoomEvent, RoomEvent};
use super::RoomEvent;
#[derive(Default)]
pub struct FakeRoomEventHandler {
pub events: Vec<RoomEvent>,
}
impl HandleRoomEvent for FakeRoomEventHandler {
impl EventHandler for FakeRoomEventHandler {
type Event = RoomEvent;
fn handle(
&mut self,
_context: &mut Context,
event: RoomEvent,
event: Self::Event,
) -> anyhow::Result<()> {
self.events.push(event);
Ok(())
@ -229,9 +223,10 @@ mod tests {
use crate::clock::SimulatedSystemClock;
use crate::context::{ContextBundle, ContextOptions};
use crate::control;
use crate::event::EventHandler;
use crate::room::{RoomMembership, RoomMessage, RoomState, RoomVisibility};
use super::{HandleRoomEvent, RoomEvent, RoomEventHandler};
use super::{RoomEvent, RoomEventHandler};
#[test]
fn handle_join_request_failure() {


Loading…
Cancel
Save