forked from lavina/lavina
1
0
Fork 0

reorder modules a bit

This commit is contained in:
Nikita Vilunov 2023-02-04 02:01:49 +01:00
parent b7995584f0
commit f9a6d8bdfc
9 changed files with 43 additions and 20 deletions

3
src/core/mod.rs Normal file
View File

@ -0,0 +1,3 @@
//! Domain definitions and implementation of common chat logic.
pub mod player;
pub mod room;

View File

@ -1,3 +1,12 @@
//! Domain of chat participants.
//!
//! Player is a single user account, which is used to participate in chats,
//! including sending messages, receiving messaged, retrieving history and running privileged actions.
//! A player corresponds to a single user account. Usually a person has only one account,
//! but it is possible to have multiple accounts for one person and therefore multiple player entities.
//!
//! A player actor is a serial handler of commands from a single player. It is preferable to run all per-player validations in the player actor,
//! so that they don't overload the room actor.
use std::{
collections::HashMap,
sync::{Arc, RwLock},
@ -9,14 +18,15 @@ use tokio::{
};
use crate::{
room::{RoomId, RoomRegistry},
table::AnonTable,
core::room::{RoomId, RoomRegistry},
util::table::AnonTable,
};
/// Opaque player id
/// Opaque player identifier.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PlayerId(u64);
/// Handle to a player actor.
#[derive(Clone)]
pub struct PlayerHandle {
tx: Sender<PlayerCommand>,
@ -58,6 +68,7 @@ impl PlayerHandle {
}
}
/// Player update event type which is sent to a connection handler.
pub enum Updates {
RoomJoined { room_id: RoomId },
NewMessage { room_id: RoomId, body: String },
@ -81,6 +92,7 @@ enum PlayerCommand {
},
}
/// Handle to a player registry — a shared data structure containing information about players.
#[derive(Clone)]
pub struct PlayerRegistry(Arc<RwLock<PlayerRegistryInner>>);
impl PlayerRegistry {
@ -106,12 +118,14 @@ impl PlayerRegistry {
}
}
/// The player registry state representation.
struct PlayerRegistryInner {
next_id: PlayerId,
room_registry: RoomRegistry,
players: HashMap<PlayerId, (PlayerHandle, JoinHandle<Player>)>,
}
/// Player actor inner state representation.
struct Player {
sockets: AnonTable<Sender<Updates>>,
}

View File

@ -1,3 +1,4 @@
//! Domain of rooms — chats with multiple participants.
use std::{
collections::HashMap,
hash::Hash,
@ -7,7 +8,7 @@ use std::{
use tokio::sync::mpsc::{channel, Sender};
use crate::{
player::{PlayerHandle, PlayerId},
core::player::{PlayerHandle, PlayerId},
prelude::*,
};

View File

@ -1,6 +1,7 @@
use crate::player::PlayerRegistry;
use crate::core::player::PlayerRegistry;
use crate::core::room::*;
use crate::prelude::*;
use crate::room::*;
use crate::projections::trivial::handle_request;
use std::convert::Infallible;
@ -14,8 +15,6 @@ use tokio::net::TcpListener;
use tokio::sync::oneshot::Sender;
use tokio::task::JoinHandle;
mod ws;
type BoxBody = http_body_util::combinators::BoxBody<Bytes, Infallible>;
async fn hello(
@ -48,9 +47,7 @@ async fn route(
) -> std::result::Result<Response<BoxBody>, Infallible> {
match (request.method(), request.uri().path()) {
(&Method::GET, "/hello") => Ok(hello(request).await?.map(BodyExt::boxed)),
(&Method::GET, "/socket") => Ok(ws::handle_request(request, chats)
.await?
.map(BodyExt::boxed)),
(&Method::GET, "/socket") => Ok(handle_request(request, chats).await?.map(BodyExt::boxed)),
(&Method::GET, "/metrics") => Ok(metrics(registry)?.map(BodyExt::boxed)),
_ => Ok(not_found()?.map(BodyExt::boxed)),
}

View File

@ -1,13 +1,13 @@
mod core;
mod http;
mod player;
mod prelude;
mod room;
mod table;
mod projections;
mod tcp;
mod util;
use crate::player::PlayerRegistry;
use crate::core::player::PlayerRegistry;
use crate::core::room::RoomRegistry;
use crate::prelude::*;
use crate::room::*;
use prometheus::{IntCounter, Opts, Registry};
use tcp::ClientSocketActor;

2
src/projections/mod.rs Normal file
View File

@ -0,0 +1,2 @@
//! Protocol projections — implementations of public APIs.
pub mod trivial;

View File

@ -1,3 +1,4 @@
//! Projection into a primitive WebSocket-based protocol for testing.
use http_body_util::Empty;
use hyper::body::Incoming;
use hyper::header::{
@ -18,8 +19,8 @@ use tokio_tungstenite::WebSocketStream;
use futures_util::sink::SinkExt;
use futures_util::stream::StreamExt;
use crate::player::{PlayerRegistry, Updates};
use crate::room::RoomId;
use crate::core::player::{PlayerRegistry, Updates};
use crate::core::room::RoomId;
enum WsCommand {
CreateRoom,

1
src/util/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod table;

View File

@ -1,7 +1,9 @@
use std::collections::HashMap;
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub struct Key(u32);
/// Hash map with auto-generated surrogate key.
pub struct AnonTable<V> {
next: u32,
inner: HashMap<u32, V>,
@ -15,10 +17,12 @@ impl<V> AnonTable<V> {
}
}
pub fn insert(&mut self, value: V) -> Option<V> {
/// Generate a free key and insert a table under that key.
pub fn insert(&mut self, value: V) -> Key {
let id = self.next;
self.next += 1;
self.inner.insert(id, value)
self.inner.insert(id, value); // should be always empty
Key(id)
}
pub fn get_mut(&mut self, key: Key) -> Option<&mut V> {