Added peer families to StateDB. Relates to #5

This commit is contained in:
Philip (a-0) 2024-02-10 20:48:58 +01:00
parent 4b00cef7e7
commit a8a8d2968b
7 changed files with 193 additions and 8 deletions

View file

@ -0,0 +1,20 @@
use serde::{Deserialize, Serialize};
use super::{FamilyId, PeerId};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Family {
pub id: FamilyId,
pub name: Option<String>,
pub members: Vec<PeerId>,
}
impl Family {
pub fn new(id: FamilyId, name: Option<String>, members: Vec<PeerId>) -> Self {
Family {
id,
name,
members,
}
}
}

View file

@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Serialize, Deserialize, Clone, Debug, Default, Ord, PartialOrd, PartialEq, Eq, Hash)]
pub struct FamilyId(Uuid);
impl FamilyId {
pub fn new() -> Self {
FamilyId { 0: Uuid::new_v4() }
}
}

View file

@ -10,6 +10,12 @@ pub use element_id::ElementId;
mod element; mod element;
pub use element::Element; pub use element::Element;
mod family_id;
pub use family_id::FamilyId;
mod family;
pub use family::Family;
mod message_id; mod message_id;
pub use message_id::MessageId; pub use message_id::MessageId;

View file

@ -2,7 +2,7 @@ use anyhow::bail;
use i2p::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs}; use i2p::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PeerId { pub struct PeerId {
i2p_addr: I2pSocketAddr, i2p_addr: I2pSocketAddr,
} }

View file

@ -2,18 +2,20 @@ use bonsaidb::core::schema::Schema;
use apps::DbApp; use apps::DbApp;
use elements::DbElement; use elements::DbElement;
use peer_families::DbPeerFamily;
use peers::DbPeer; use peers::DbPeer;
use pot_memberships::DbPotMembership; use pot_memberships::DbPotMembership;
use pots::DbPot; use pots::DbPot;
mod apps; mod apps;
mod elements; mod elements;
mod peer_families;
mod peers; mod peers;
mod pot_memberships; mod pot_memberships;
mod pots; mod pots;
#[derive(Schema, Debug)] #[derive(Schema, Debug)]
#[schema(name = "ubisync", collections = [DbElement, DbPotMembership, DbApp, DbPot, DbPeer])] #[schema(name = "ubisync", collections = [DbElement, DbPotMembership, DbApp, DbPot, DbPeer, DbPeerFamily])]
pub struct UbisyncSchema; pub struct UbisyncSchema;
#[cfg(test)] #[cfg(test)]

View file

@ -0,0 +1,144 @@
use std::collections::HashSet;
use anyhow::{anyhow, Error};
use bonsaidb::core::schema::{Collection, SerializedCollection};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use ubisync_lib::types::{Family, FamilyId, PeerId};
use crate::state::database::{as_key::AsKey, StateDB};
#[derive(Debug, Serialize, Deserialize, Collection, PartialEq, Clone)]
#[collection(name = "peer-families", views = [])]
pub(super) struct DbPeerFamily {
#[natural_id]
pub(super) id: AsKey<FamilyId>,
pub(super) name: Option<String>,
pub(super) members: HashSet<PeerId>,
}
impl From<DbPeerFamily> for Family {
fn from(value: DbPeerFamily) -> Self {
Family {
id: (*value.id).clone(),
name: value.name,
members: value.members.iter().map(|p| p.clone()).collect_vec(),
}
}
}
impl StateDB {
pub fn add_peer_family(
&self,
id: FamilyId,
name: Option<String>,
initial_members: Vec<PeerId>,
) -> anyhow::Result<()> {
DbPeerFamily::push(
DbPeerFamily {
id: AsKey::new(id),
name,
members: HashSet::from_iter(initial_members),
},
&self.db,
)
.map(|_| ())
.map_err(|e| anyhow!(e))
}
pub fn add_peer_to_family(&self, peer: PeerId, family: FamilyId) -> anyhow::Result<()> {
DbPeerFamily::get(&AsKey::new(family), &self.db)
.map_err(|e| anyhow!(e))?
.ok_or(Error::msg("Could not find peer family"))?
.modify(&self.db, |doc| {
doc.contents.members.insert(peer.clone());
})
.map_err(|e| anyhow!(e))
}
pub fn set_peer_family_name(
&self,
family: FamilyId,
name: Option<String>,
) -> anyhow::Result<()> {
DbPeerFamily::get(&AsKey::new(family), &self.db)
.map_err(|e| anyhow!(e))?
.ok_or(Error::msg("Could not find peer family"))?
.modify(&self.db, |doc| {
doc.contents.name = name.clone();
})
.map_err(|e| anyhow!(e))
}
pub fn get_peer_family(&self, id: FamilyId) -> anyhow::Result<Option<Family>> {
DbPeerFamily::get(&AsKey::new(id), &self.db)
.map(|doc_opt| doc_opt.map(|doc| doc.contents.into()))
.map_err(|e| anyhow!(e))
}
}
#[cfg(test)]
mod tests {
use ubisync_lib::types::{Family, FamilyId, PeerId};
use crate::state::database::StateDB;
#[test]
fn add_get() {
let db = StateDB::init(None);
let family_id = FamilyId::new();
let peer_id = PeerId::default();
db.add_peer_family(
family_id.clone(),
Some("My family name".to_string()),
vec![peer_id.clone()],
)
.unwrap();
let retrieved_family = db.get_peer_family(family_id.clone()).unwrap();
assert_eq!(
retrieved_family,
Some(Family::new(
family_id,
Some("My family name".to_string()),
vec![peer_id]
))
)
}
#[test]
fn set_name() {
let db = StateDB::init(None);
let family_id = FamilyId::new();
let peer_id = PeerId::default();
db.add_peer_family(
family_id.clone(),
Some("My family name".to_string()),
vec![peer_id.clone()],
)
.unwrap();
assert_eq!(
db.get_peer_family(family_id.clone()).unwrap(),
Some(Family::new(
family_id.clone(),
Some("My family name".to_string()),
vec![peer_id.clone()]
))
);
db.set_peer_family_name(family_id.clone(), Some("New family name".to_string()))
.unwrap();
assert_eq!(
db.get_peer_family(family_id.clone()).unwrap(),
Some(Family::new(
family_id,
Some("New family name".to_string()),
vec![peer_id]
))
);
}
}

View file

@ -2,10 +2,7 @@ use anyhow::{anyhow, Error};
use bonsaidb::core::schema::{Collection, SerializedCollection}; use bonsaidb::core::schema::{Collection, SerializedCollection};
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ubisync_lib::{ use ubisync_lib::{peer::Peer, types::PeerId};
peer::Peer,
types::{self, PeerId},
};
use crate::state::database::{as_key::AsKey, StateDB}; use crate::state::database::{as_key::AsKey, StateDB};
@ -13,7 +10,7 @@ use crate::state::database::{as_key::AsKey, StateDB};
#[collection(name = "peers", views = [])] #[collection(name = "peers", views = [])]
pub(super) struct DbPeer { pub(super) struct DbPeer {
#[natural_id] #[natural_id]
pub(super) id: AsKey<types::PeerId>, pub(super) id: AsKey<PeerId>,
pub(super) name: Option<String>, pub(super) name: Option<String>,
} }
@ -45,7 +42,12 @@ impl StateDB {
pub fn get_all_peers(&self) -> anyhow::Result<Vec<Peer>> { pub fn get_all_peers(&self) -> anyhow::Result<Vec<Peer>> {
DbPeer::all(&self.db) DbPeer::all(&self.db)
.query() .query()
.map(|peers| peers.iter().map(|p| p.contents.clone().into()).collect_vec()) .map(|peers| {
peers
.iter()
.map(|p| p.contents.clone().into())
.collect_vec()
})
.map_err(|e| anyhow!(e)) .map_err(|e| anyhow!(e))
} }