Add functions to add peers to a family in Ubisync. Relates to #5

This commit is contained in:
Philip (a-0) 2024-02-10 22:44:38 +01:00
parent a8a8d2968b
commit 6581c3b9c6
5 changed files with 99 additions and 8 deletions

View file

@ -160,6 +160,10 @@ impl CommHandle {
Ok(i2p_dest)
}
pub fn own_peer_id(&self) -> anyhow::Result<PeerId> {
Ok(self.i2p_address()?.into())
}
fn read_connection(
wrapped_stream: Arc<RwLock<I2pStream>>,
state: Arc<CommState>,

View file

@ -61,14 +61,19 @@ impl Ubisync {
pub fn add_peer(&self, p: impl TryInto<Peer, Error = anyhow::Error>) -> anyhow::Result<()> {
match p.try_into() {
Ok(peer) => self.state_handle.set_peer(peer),
Ok(peer) => self.state_handle.add_peer(peer),
Err(e) => bail!(e),
}
}
pub fn add_peer_from_id(&self, id: PeerId) -> anyhow::Result<()> {
// TODO: resolve peer's name before setting
self.state_handle.set_peer(Peer::new(id, None))
self.state_handle.add_peer(Peer::new(id, None))
}
pub fn add_family_member_from_id(&self, id: PeerId) -> anyhow::Result<()> {
self.add_peer_from_id(id.clone())?;
self.state_handle.add_family_member(id)
}
pub fn get_apps(&self) -> Vec<App> {

View file

@ -1,7 +1,11 @@
use std::collections::HashSet;
use anyhow::{anyhow, Error};
use bonsaidb::core::schema::{Collection, SerializedCollection};
use bonsaidb::core::{
connection::Connection,
document::Emit,
schema::{view::map::Mappings, Collection, MapReduce, SerializedCollection, View, ViewSchema},
};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use ubisync_lib::types::{Family, FamilyId, PeerId};
@ -9,7 +13,7 @@ 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 = [])]
#[collection(name = "peer-families", views = [DbPeerFamilyByMemberId])]
pub(super) struct DbPeerFamily {
#[natural_id]
pub(super) id: AsKey<FamilyId>,
@ -17,6 +21,33 @@ pub(super) struct DbPeerFamily {
pub(super) members: HashSet<PeerId>,
}
#[derive(Debug, Clone, View, ViewSchema)]
#[view(collection = DbPeerFamily, key = AsKey<PeerId>, value = Option<FamilyId>, name = "by-member-id")]
pub(super) struct DbPeerFamilyByMemberId;
impl MapReduce for DbPeerFamilyByMemberId {
fn map<'doc>(
&self,
document: &'doc bonsaidb::core::document::BorrowedDocument<'_>,
) -> bonsaidb::core::schema::ViewMapResult<'doc, Self> {
let content = DbPeerFamily::document_contents(document)?;
Ok(content
.members
.iter()
.fold(Mappings::default(), |acc, member| {
acc.and(
document
.header
.emit_key_and_value(
AsKey::new(member.to_owned()),
Some((*content.id).clone()),
)
.unwrap_or(Mappings::none()),
)
}))
}
}
impl From<DbPeerFamily> for Family {
fn from(value: DbPeerFamily) -> Self {
Family {
@ -75,6 +106,19 @@ impl StateDB {
.map(|doc_opt| doc_opt.map(|doc| doc.contents.into()))
.map_err(|e| anyhow!(e))
}
pub fn get_family_of_peer(&self, peer: PeerId) -> anyhow::Result<Option<FamilyId>> {
self.db
.view::<DbPeerFamilyByMemberId>()
.with_key(&AsKey::new(peer))
.query_with_collection_docs()
.map(|results| match results.mappings.len() {
0 => Ok(None),
1 => Ok(results.mappings.first().unwrap().value.clone()),
_ => Err(Error::msg("Peer appears to be member of multiple families")),
})?
.map_err(|e| anyhow!(e))
}
}
#[cfg(test)]
@ -141,4 +185,20 @@ mod tests {
))
);
}
#[test]
fn get_family_of_peer() {
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_family_of_peer(peer_id).unwrap(), Some(family_id))
}
}

View file

@ -10,7 +10,7 @@ use ubisync_lib::{
api::events::AppEvent,
messages::{Message, MessageContent},
peer::Peer,
types::{AppId, Element, ElementContent, ElementId, PotId, Tag},
types::{AppId, Element, ElementContent, ElementId, FamilyId, PeerId, PotId, Tag},
};
use anyhow::Error;
@ -101,7 +101,7 @@ impl State {
todo!()
}
pub fn set_peer(&self, peer: Peer) -> anyhow::Result<()> {
pub fn add_peer(&self, peer: Peer) -> anyhow::Result<()> {
self.db.add_peer(peer)
}
@ -127,6 +127,28 @@ impl State {
})
}
pub fn add_family_member(&self, peer: PeerId) -> anyhow::Result<()> {
let my_id = self
.comm_handle
.read()
.map_err(|_| Error::msg("Failed to lock on CommHandle"))?
.to_owned()
.ok_or(Error::msg("CommHandle not initialized"))?
.own_peer_id()?;
if self.db.get_family_of_peer(my_id.clone())?.is_none() {
self.db
.add_peer_family(FamilyId::new(), None, vec![my_id.clone()])?;
}
self.db.add_peer_to_family(
peer,
self.db
.get_family_of_peer(my_id)?
.ok_or(Error::msg("Could not find own family"))?,
)
}
pub fn get_event_receiver(
&self,
app: &AppId,

View file

@ -23,7 +23,7 @@ async fn two_nodes_element_creation() {
c2.api_config.port = Some(9982);
let ubi1 = Ubisync::new(&Config::default()).await.unwrap();
let ubi2 = Arc::new(Ubisync::new(&c2).await.unwrap());
ubi1.add_peer_from_id(ubi2.get_destination().unwrap().into())
ubi1.add_family_member_from_id(ubi2.get_destination().unwrap().into())
.unwrap();
let api_client1 =
@ -92,7 +92,7 @@ async fn two_nodes_api_event() {
c2.api_config.port = Some(9982);
let ubi1 = Arc::new(Ubisync::new(&Config::default()).await.unwrap());
let ubi2 = Ubisync::new(&c2).await.unwrap();
ubi2.add_peer_from_id(ubi1.get_destination().unwrap().into())
ubi2.add_family_member_from_id(ubi1.get_destination().unwrap().into())
.unwrap();
let api_client1 =