From 80ad6aa8d6bc26bbfa65acc6026bc1199a2a6533 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 28 Nov 2023 14:22:59 +0100 Subject: [PATCH] refactoring --- src/api.rs | 87 ++--------------------------- src/database.rs | 58 ++++++++++++++++++- src/federation/activities/mod.rs | 36 ++++++++++++ src/federation/activities/reject.rs | 2 +- src/lib.rs | 2 +- 5 files changed, 99 insertions(+), 86 deletions(-) diff --git a/src/api.rs b/src/api.rs index 90be32f..586721f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,10 +1,9 @@ -use crate::database::DatabaseHandle; -use crate::error::{Error, MyResult}; +use crate::database::{DatabaseHandle, DbConflict}; +use crate::error::MyResult; use crate::federation::activities::create_article::CreateArticle; -use crate::federation::activities::update_local_article::UpdateLocalArticle; -use crate::federation::activities::update_remote_article::UpdateRemoteArticle; +use crate::federation::activities::submit_article_update; use crate::federation::objects::article::DbArticle; -use crate::federation::objects::edit::{DbEdit, EditVersion}; +use crate::federation::objects::edit::EditVersion; use crate::federation::objects::instance::DbInstance; use crate::utils::generate_article_version; use activitypub_federation::config::Data; @@ -14,7 +13,7 @@ use axum::extract::Query; use axum::routing::{get, post}; use axum::{Form, Json, Router}; use axum_macros::debug_handler; -use diffy::{apply, create_patch, merge, Patch}; +use diffy::create_patch; use futures::future::try_join_all; use rand::random; use serde::{Deserialize, Serialize}; @@ -85,54 +84,6 @@ pub struct ApiConflict { pub previous_version: EditVersion, } -#[derive(Clone, Debug)] -pub struct DbConflict { - pub id: i32, - pub diff: String, - pub article_id: ObjectId, - pub previous_version: EditVersion, -} - -impl DbConflict { - pub async fn to_api_conflict( - &self, - data: &Data, - ) -> MyResult> { - let original_article = { - let mut lock = data.articles.lock().unwrap(); - let article = lock.get_mut(self.article_id.inner()).unwrap(); - article.clone() - }; - - // create common ancestor version - let ancestor = generate_article_version(&original_article.edits, &self.previous_version)?; - - let patch = Patch::from_str(&self.diff)?; - // apply self.diff to ancestor to get `ours` - let ours = apply(&ancestor, &patch)?; - match merge(&ancestor, &ours, &original_article.text) { - Ok(new_text) => { - // patch applies cleanly so we are done - // federate the change - submit_article_update(data, new_text, &original_article).await?; - // remove conflict from db - let mut lock = data.conflicts.lock().unwrap(); - lock.retain(|c| c.id != self.id); - Ok(None) - } - Err(three_way_merge) => { - // there is a merge conflict, user needs to do three-way-merge - Ok(Some(ApiConflict { - id: self.id, - three_way_merge, - article_id: original_article.ap_id.clone(), - previous_version: original_article.latest_version, - })) - } - } - } -} - #[debug_handler] async fn edit_article( data: Data, @@ -177,34 +128,6 @@ async fn edit_article( } } -async fn submit_article_update( - data: &Data, - new_text: String, - original_article: &DbArticle, -) -> Result<(), Error> { - let edit = DbEdit::new(original_article, &new_text)?; - if original_article.local { - let updated_article = { - let mut lock = data.articles.lock().unwrap(); - let article = lock.get_mut(original_article.ap_id.inner()).unwrap(); - article.text = new_text; - article.latest_version = edit.version.clone(); - article.edits.push(edit.clone()); - article.clone() - }; - - UpdateLocalArticle::send(updated_article, vec![], data).await?; - } else { - UpdateRemoteArticle::send( - edit, - original_article.instance.dereference(data).await?, - data, - ) - .await?; - } - Ok(()) -} - #[derive(Deserialize, Serialize, Clone)] pub struct GetArticleData { pub title: String, diff --git a/src/database.rs b/src/database.rs index c4db08e..8c106be 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,7 +1,13 @@ -use crate::api::DbConflict; +use crate::api::ApiConflict; +use crate::error::MyResult; +use crate::federation::activities::submit_article_update; use crate::federation::objects::article::DbArticle; - +use crate::federation::objects::edit::EditVersion; use crate::federation::objects::instance::DbInstance; +use crate::utils::generate_article_version; +use activitypub_federation::config::Data; +use activitypub_federation::fetch::object_id::ObjectId; +use diffy::{apply, merge, Patch}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use url::Url; @@ -20,3 +26,51 @@ impl Database { lock.iter().find(|i| i.1.local).unwrap().1.clone() } } + +#[derive(Clone, Debug)] +pub struct DbConflict { + pub id: i32, + pub diff: String, + pub article_id: ObjectId, + pub previous_version: EditVersion, +} + +impl DbConflict { + pub async fn to_api_conflict( + &self, + data: &Data, + ) -> MyResult> { + let original_article = { + let mut lock = data.articles.lock().unwrap(); + let article = lock.get_mut(self.article_id.inner()).unwrap(); + article.clone() + }; + + // create common ancestor version + let ancestor = generate_article_version(&original_article.edits, &self.previous_version)?; + + let patch = Patch::from_str(&self.diff)?; + // apply self.diff to ancestor to get `ours` + let ours = apply(&ancestor, &patch)?; + match merge(&ancestor, &ours, &original_article.text) { + Ok(new_text) => { + // patch applies cleanly so we are done + // federate the change + submit_article_update(data, new_text, &original_article).await?; + // remove conflict from db + let mut lock = data.conflicts.lock().unwrap(); + lock.retain(|c| c.id != self.id); + Ok(None) + } + Err(three_way_merge) => { + // there is a merge conflict, user needs to do three-way-merge + Ok(Some(ApiConflict { + id: self.id, + three_way_merge, + article_id: original_article.ap_id.clone(), + previous_version: original_article.latest_version, + })) + } + } + } +} diff --git a/src/federation/activities/mod.rs b/src/federation/activities/mod.rs index c5ef681..ea9ead4 100644 --- a/src/federation/activities/mod.rs +++ b/src/federation/activities/mod.rs @@ -1,6 +1,42 @@ +use crate::database::DatabaseHandle; +use crate::error::Error; +use crate::federation::activities::update_local_article::UpdateLocalArticle; +use crate::federation::activities::update_remote_article::UpdateRemoteArticle; +use crate::federation::objects::article::DbArticle; +use crate::federation::objects::edit::DbEdit; +use activitypub_federation::config::Data; + pub mod accept; pub mod create_article; pub mod follow; pub mod reject; pub mod update_local_article; pub mod update_remote_article; + +pub async fn submit_article_update( + data: &Data, + new_text: String, + original_article: &DbArticle, +) -> Result<(), Error> { + let edit = DbEdit::new(original_article, &new_text)?; + if original_article.local { + let updated_article = { + let mut lock = data.articles.lock().unwrap(); + let article = lock.get_mut(original_article.ap_id.inner()).unwrap(); + article.text = new_text; + article.latest_version = edit.version.clone(); + article.edits.push(edit.clone()); + article.clone() + }; + + UpdateLocalArticle::send(updated_article, vec![], data).await?; + } else { + UpdateRemoteArticle::send( + edit, + original_article.instance.dereference(data).await?, + data, + ) + .await?; + } + Ok(()) +} diff --git a/src/federation/activities/reject.rs b/src/federation/activities/reject.rs index c71ece1..136f03f 100644 --- a/src/federation/activities/reject.rs +++ b/src/federation/activities/reject.rs @@ -10,7 +10,7 @@ use activitypub_federation::{ }; use rand::random; -use crate::api::DbConflict; +use crate::database::DbConflict; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/src/lib.rs b/src/lib.rs index 18614af..707e1b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ use std::net::ToSocketAddrs; use tracing::info; pub mod api; -mod database; +pub mod database; pub mod error; pub mod federation; mod utils;