Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
radicle: implement caching for issues and patches
Fintan Halpenny committed 2 years ago
commit 02fb9397e8dbf53c5cbfb675d09bdb9eb7443ba1
parent 67e46952b62a6663ea30dcf109b85cf9058f1133
5 files changed +44 -28
modified radicle-httpd/src/api.rs
@@ -9,6 +9,8 @@ use axum::http::Method;
use axum::response::{IntoResponse, Json};
use axum::routing::get;
use axum::Router;
+
use radicle::issue::cache::Issues as _;
+
use radicle::patch::cache::Patches as _;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio::sync::RwLock;
@@ -60,8 +62,8 @@ impl Context {

        let payload = doc.project()?;
        let delegates = doc.delegates;
-
        let issues = issue::Issues::open(&repo)?.counts()?;
-
        let patches = patch::Patches::open(&repo)?.counts()?;
+
        let issues = self.profile.issues(&repo)?.counts()?;
+
        let patches = self.profile.patches(&repo)?.counts()?;
        let db = &self.profile.database()?;
        let seeding = db.count(&id).unwrap_or_default();

modified radicle-httpd/src/api/error.rs
@@ -30,6 +30,14 @@ pub enum Error {
    #[error(transparent)]
    Storage(#[from] radicle::storage::Error),

+
    /// Cob cache error.
+
    #[error(transparent)]
+
    CobCache(#[from] radicle::cob::cache::Error),
+

+
    /// Cob issue cache error.
+
    #[error(transparent)]
+
    CacheIssue(#[from] radicle::cob::issue::cache::Error),
+

    /// Cob issue error.
    #[error(transparent)]
    CobIssue(#[from] radicle::cob::issue::Error),
@@ -38,6 +46,10 @@ pub enum Error {
    #[error(transparent)]
    CobPatch(#[from] radicle::cob::patch::Error),

+
    /// Cob patch cache error.
+
    #[error(transparent)]
+
    CachePatch(#[from] radicle::cob::patch::cache::Error),
+

    /// Cob store error.
    #[error(transparent)]
    CobStore(#[from] radicle::cob::store::Error),
@@ -123,6 +135,7 @@ impl IntoResponse for Error {
            Error::BadRequest(msg) => (StatusCode::BAD_REQUEST, Some(msg)),
            other => {
                tracing::error!("Error: {message}");
+
                tracing::debug!("Error Debug: {:?}", other);

                if cfg!(debug_assertions) {
                    (StatusCode::INTERNAL_SERVER_ERROR, Some(other.to_string()))
modified radicle-httpd/src/api/v1/delegates.rs
@@ -5,10 +5,10 @@ use axum::response::IntoResponse;
use axum::routing::get;
use axum::{Json, Router};

-
use radicle::cob::issue::Issues;
-
use radicle::cob::patch::Patches;
use radicle::identity::{Did, Visibility};
+
use radicle::issue::cache::Issues as _;
use radicle::node::routing::Store;
+
use radicle::patch::cache::Patches as _;
use radicle::storage::{ReadRepository, ReadStorage};

use crate::api::error::Error;
@@ -44,7 +44,6 @@ async fn delegates_projects_handler(
    let storage = &ctx.profile.storage;
    let db = &ctx.profile.database()?;
    let pinned = &ctx.profile.config.web.pinned;
-

    let mut projects = match show {
        ProjectQuery::All => storage
            .repositories()?
@@ -73,13 +72,13 @@ async fn delegates_projects_handler(
            let Ok(payload) = id.doc.project() else {
                return None;
            };
-
            let Ok(issues) = Issues::open(&repo) else {
+
            let Ok(issues) = ctx.profile.issues(&repo) else {
                return None;
            };
            let Ok(issues) = issues.counts() else {
                return None;
            };
-
            let Ok(patches) = Patches::open(&repo) else {
+
            let Ok(patches) = ctx.profile.patches(&repo) else {
                return None;
            };
            let Ok(patches) = patches.counts() else {
modified radicle-httpd/src/api/v1/projects.rs
@@ -14,7 +14,10 @@ use serde::{Deserialize, Serialize};
use serde_json::json;
use tower_http::set_header::SetResponseHeaderLayer;

-
use radicle::cob::{issue, patch, resolve_embed, Embed, Label, Uri};
+
use radicle::cob::{
+
    issue, issue::cache::Issues as _, patch, patch::cache::Patches as _, resolve_embed, Embed,
+
    Label, Uri,
+
};
use radicle::identity::{Did, RepoId, Visibility};
use radicle::node::routing::Store;
use radicle::node::{AliasStore, Node, NodeId};
@@ -126,13 +129,13 @@ async fn project_root_handler(
            let Ok(payload) = info.doc.project() else {
                return None;
            };
-
            let Ok(issues) = issue::Issues::open(&repo) else {
+
            let Ok(issues) = ctx.profile.issues(&repo) else {
                return None;
            };
            let Ok(issues) = issues.counts() else {
                return None;
            };
-
            let Ok(patches) = patch::Patches::open(&repo) else {
+
            let Ok(patches) = ctx.profile.patches(&repo) else {
                return None;
            };
            let Ok(patches) = patches.counts() else {
@@ -587,9 +590,9 @@ async fn issues_handler(
    let state = state.unwrap_or_default();
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let issues = issue::Issues::open(&repo)?;
+
    let issues = ctx.profile.issues(&repo)?;
    let mut issues: Vec<_> = issues
-
        .all()?
+
        .list()?
        .filter_map(|r| {
            let (id, issue) = r.ok()?;
            (state.matches(issue.state())).then_some((id, issue))
@@ -639,7 +642,7 @@ async fn issue_create_handler(
        .filter_map(|embed| resolve_embed(&repo, embed))
        .collect();

-
    let mut issues = issue::Issues::open(&repo)?;
+
    let mut issues = ctx.profile.issues_mut(&repo)?;
    let issue = issues
        .create(
            issue.title,
@@ -672,7 +675,7 @@ async fn issue_update_handler(
    let storage = &ctx.profile.storage;
    let signer = ctx.profile.signer()?;
    let repo = storage.repository(project)?;
-
    let mut issues = issue::Issues::open(&repo)?;
+
    let mut issues = ctx.profile.issues_mut(&repo)?;
    let mut issue = issues.get_mut(&issue_id.into())?;

    let id = match action {
@@ -723,7 +726,9 @@ async fn issue_handler(
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let issue = issue::Issues::open(&repo)?
+
    let issue = ctx
+
        .profile
+
        .issues(&repo)?
        .get(&issue_id.into())?
        .ok_or(Error::NotFound)?;
    let aliases = ctx.profile.aliases();
@@ -756,7 +761,7 @@ async fn patch_create_handler(
        .signer()
        .map_err(|_| Error::Auth("Unauthorized"))?;
    let repo = storage.repository(project)?;
-
    let mut patches = patch::Patches::open(&repo)?;
+
    let mut patches = ctx.profile.patches_mut(&repo)?;
    let base_oid = repo.raw().merge_base(*patch.target, *patch.oid)?;

    let patch = patches
@@ -795,7 +800,7 @@ async fn patch_update_handler(
        .signer()
        .map_err(|_| Error::Auth("Unauthorized"))?;
    let repo = storage.repository(project)?;
-
    let mut patches = patch::Patches::open(&repo)?;
+
    let mut patches = ctx.profile.patches_mut(&repo)?;
    let mut patch = patches.get_mut(&patch_id.into())?;
    let id = match action {
        patch::Action::Edit { title, target } => patch.edit(title, target, &signer)?,
@@ -940,9 +945,9 @@ async fn patches_handler(
    let state = state.unwrap_or_default();
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let patches = patch::Patches::open(&repo)?;
+
    let patches = ctx.profile.patches(&repo)?;
    let mut patches = patches
-
        .all()?
+
        .list()?
        .filter_map(|r| {
            let (id, patch) = r.ok()?;
            (state.matches(patch.state())).then_some((id, patch))
@@ -968,9 +973,8 @@ async fn patch_handler(
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let patch = patch::Patches::open(&repo)?
-
        .get(&patch_id.into())?
-
        .ok_or(Error::NotFound)?;
+
    let patches = ctx.profile.patches(&repo)?;
+
    let patch = patches.get(&patch_id.into())?.ok_or(Error::NotFound)?;
    let aliases = ctx.profile.aliases();

    Ok::<_, Error>(Json(api::json::patch(
modified radicle-httpd/src/test.rs
@@ -11,18 +11,16 @@ use serde_json::Value;
use time::OffsetDateTime;
use tower::ServiceExt;

-
use radicle::cob::issue::Issues;
-
use radicle::cob::patch::{MergeTarget, Patches};
+
use radicle::cob::patch::MergeTarget;
use radicle::crypto::ssh::keystore::MemorySigner;
use radicle::crypto::ssh::Keystore;
use radicle::crypto::{KeyPair, Seed, Signer};
use radicle::git::{raw as git2, RefString};
use radicle::identity::Visibility;
-
use radicle::node;
-
use radicle::profile;
use radicle::profile::Home;
use radicle::storage::ReadStorage;
use radicle::Storage;
+
use radicle::{node, profile};
use radicle_crypto::test::signer::MockSigner;

use crate::api::{auth, Context};
@@ -231,7 +229,7 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G

    let storage = &profile.storage;
    let repo = storage.repository(rid).unwrap();
-
    let mut issues = Issues::open(&repo).unwrap();
+
    let mut issues = profile.issues_mut(&repo).unwrap();
    let issue = issues
        .create(
            "Issue #1".to_string(),
@@ -245,7 +243,7 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
    tracing::debug!(target: "test", "Contributor issue: {}", issue.id());

    // eq. rad patch open
-
    let mut patches = Patches::open(&repo).unwrap();
+
    let mut patches = profile.patches_mut(&repo).unwrap();
    let oid = radicle::git::Oid::from_str(HEAD).unwrap();
    let base = radicle::git::Oid::from_str(PARENT).unwrap();
    let patch = patches