mirror of
https://github.com/Nutomic/ibis.git
synced 2024-12-26 00:41:24 +00:00
refactoring
This commit is contained in:
parent
c958c26257
commit
80ad6aa8d6
5 changed files with 99 additions and 86 deletions
87
src/api.rs
87
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<DbArticle>,
|
||||
pub previous_version: EditVersion,
|
||||
}
|
||||
|
||||
impl DbConflict {
|
||||
pub async fn to_api_conflict(
|
||||
&self,
|
||||
data: &Data<DatabaseHandle>,
|
||||
) -> MyResult<Option<ApiConflict>> {
|
||||
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<DatabaseHandle>,
|
||||
|
@ -177,34 +128,6 @@ async fn edit_article(
|
|||
}
|
||||
}
|
||||
|
||||
async fn submit_article_update(
|
||||
data: &Data<DatabaseHandle>,
|
||||
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,
|
||||
|
|
|
@ -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<DbArticle>,
|
||||
pub previous_version: EditVersion,
|
||||
}
|
||||
|
||||
impl DbConflict {
|
||||
pub async fn to_api_conflict(
|
||||
&self,
|
||||
data: &Data<DatabaseHandle>,
|
||||
) -> MyResult<Option<ApiConflict>> {
|
||||
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,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<DatabaseHandle>,
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue