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 anyhow::Result;
|
||||||
use prometheus::Registry as MetricsRegistry;
|
use prometheus::Registry as MetricsRegistry;
|
||||||
|
|
||||||
|
use crate::dialog::DialogRegistry;
|
||||||
use crate::player::PlayerRegistry;
|
use crate::player::PlayerRegistry;
|
||||||
use crate::repo::Storage;
|
use crate::repo::Storage;
|
||||||
use crate::room::RoomRegistry;
|
use crate::room::RoomRegistry;
|
||||||
|
|
||||||
|
pub mod dialog;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod repo;
|
pub mod repo;
|
||||||
|
@ -18,6 +20,7 @@ mod table;
|
||||||
pub struct LavinaCore {
|
pub struct LavinaCore {
|
||||||
pub players: PlayerRegistry,
|
pub players: PlayerRegistry,
|
||||||
pub rooms: RoomRegistry,
|
pub rooms: RoomRegistry,
|
||||||
|
pub dialogs: DialogRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LavinaCore {
|
impl LavinaCore {
|
||||||
|
@ -25,7 +28,12 @@ impl LavinaCore {
|
||||||
// TODO shutdown all services in reverse order on error
|
// TODO shutdown all services in reverse order on error
|
||||||
let rooms = RoomRegistry::new(&mut metrics, storage.clone())?;
|
let rooms = RoomRegistry::new(&mut metrics, storage.clone())?;
|
||||||
let players = PlayerRegistry::empty(rooms.clone(), storage.clone(), &mut metrics)?;
|
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<()> {
|
pub async fn shutdown(mut self) -> Result<()> {
|
||||||
|
|
Loading…
Reference in New Issue