forked from lavina/lavina
initial dialogs impl
This commit is contained in:
parent
ddb348bee9
commit
662aae5075
|
@ -0,0 +1,14 @@
|
|||
create table dialogs(
|
||||
participant_1 integer not null,
|
||||
participant_2 integer not null,
|
||||
created_at timestamp not null,
|
||||
message_count integer not null default 0,
|
||||
primary key (participant_1, participant_2)
|
||||
);
|
||||
|
||||
create table dialog_messages(
|
||||
dialog_id integer not null,
|
||||
id integer not null, -- unique per dialog, sequential in one dialog
|
||||
content string not null,
|
||||
primary key (dialog_id, id)
|
||||
);
|
|
@ -0,0 +1,75 @@
|
|||
//! Domain of dialogs – conversations between two participants.
|
||||
//!
|
||||
//! Dialogs are different from rooms in that they are always between two participants.
|
||||
//! There are no
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::sync::RwLock as AsyncRwLock;
|
||||
|
||||
use crate::player::PlayerId;
|
||||
use crate::repo::Storage;
|
||||
|
||||
/// Id of a conversation between two players.
|
||||
///
|
||||
/// Dialogs are identified by the pair of participants' ids. The order of ids does not matter.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct DialogId(PlayerId, PlayerId);
|
||||
impl DialogId {
|
||||
pub fn new(a: PlayerId, b: PlayerId) -> DialogId {
|
||||
if a.as_inner() < b.as_inner() {
|
||||
DialogId(a, b)
|
||||
} else {
|
||||
DialogId(b, a)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_inner(&self) -> (&PlayerId, &PlayerId) {
|
||||
(&self.0, &self.1)
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> (PlayerId, PlayerId) {
|
||||
(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
struct Dialog {
|
||||
storage_id: u32,
|
||||
id: DialogId,
|
||||
message_count: u32,
|
||||
}
|
||||
|
||||
struct DialogRegistryInner {
|
||||
dialogs: HashMap<DialogId, AsyncRwLock<Dialog>>,
|
||||
storage: Storage,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DialogRegistry(Arc<AsyncRwLock<DialogRegistryInner>>);
|
||||
|
||||
impl DialogRegistry {
|
||||
pub fn new(storage: Storage) -> DialogRegistry {
|
||||
DialogRegistry(Arc::new(AsyncRwLock::new(DialogRegistryInner {
|
||||
dialogs: HashMap::new(),
|
||||
storage,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_dialog_id_new() {
|
||||
let a = PlayerId::from("a").unwrap();
|
||||
let b = PlayerId::from("b").unwrap();
|
||||
let id1 = DialogId::new(a.clone(), b.clone());
|
||||
let id2 = DialogId::new(a.clone(), b.clone());
|
||||
// Dialog ids are invariant with respect to the order of participants
|
||||
assert_eq!(id1, id2);
|
||||
assert_eq!(id1.as_inner(), (&a, &b));
|
||||
assert_eq!(id2.as_inner(), (&a, &b));
|
||||
}
|
||||
}
|
|
@ -2,10 +2,12 @@
|
|||
use anyhow::Result;
|
||||
use prometheus::Registry as MetricsRegistry;
|
||||
|
||||
use crate::dialog::DialogRegistry;
|
||||
use crate::player::PlayerRegistry;
|
||||
use crate::repo::Storage;
|
||||
use crate::room::RoomRegistry;
|
||||
|
||||
pub mod dialog;
|
||||
pub mod player;
|
||||
pub mod prelude;
|
||||
pub mod repo;
|
||||
|
@ -18,6 +20,7 @@ mod table;
|
|||
pub struct LavinaCore {
|
||||
pub players: PlayerRegistry,
|
||||
pub rooms: RoomRegistry,
|
||||
pub dialogs: DialogRegistry,
|
||||
}
|
||||
|
||||
impl LavinaCore {
|
||||
|
@ -25,7 +28,12 @@ impl LavinaCore {
|
|||
// TODO shutdown all services in reverse order on error
|
||||
let rooms = RoomRegistry::new(&mut metrics, storage.clone())?;
|
||||
let players = PlayerRegistry::empty(rooms.clone(), storage.clone(), &mut metrics)?;
|
||||
Ok(LavinaCore { players, rooms })
|
||||
let dialogs = DialogRegistry::new(storage.clone());
|
||||
Ok(LavinaCore {
|
||||
players,
|
||||
rooms,
|
||||
dialogs,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn shutdown(mut self) -> Result<()> {
|
||||
|
|
Loading…
Reference in New Issue