http: Only count publicly seeded repositories

Previously the /api/v1/stats endpoint would count any repository that is
in the storage regardless of whether the repository is publicly seeded or not.
This commit is contained in:
Rūdolfs Ošiņš
2024-07-19 05:32:42 -03:00
committed by Sebastian Martinez
parent 662a5e24eb
commit b105d06fae
5 changed files with 59 additions and 19 deletions
+4 -4
View File
@@ -167,7 +167,7 @@ mod routes {
"closed": 0,
},
"id": RID,
"seeding": 0,
"seeding": 1,
},
{
"name": "again-hello-world",
@@ -195,7 +195,7 @@ mod routes {
"closed": 0,
},
"id": "rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE",
"seeding": 0,
"seeding": 1,
}
])
);
@@ -245,7 +245,7 @@ mod routes {
"closed": 0,
},
"id": RID,
"seeding": 0,
"seeding": 1,
},
{
"name": "again-hello-world",
@@ -273,7 +273,7 @@ mod routes {
"closed": 0,
},
"id": "rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE",
"seeding": 0,
"seeding": 1,
}
])
);
+17 -2
View File
@@ -112,7 +112,7 @@ mod routes {
use axum::extract::connect_info::MockConnectInfo;
use axum::http::StatusCode;
use pretty_assertions::assert_eq;
use serde_json::json;
use serde_json::{json, Value};
use crate::test::*;
@@ -206,6 +206,21 @@ mod routes {
let response = get(&app, format!("/nodes/{nid}/inventory")).await;
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(response.json().await, json!([]));
let json_response = response.json().await;
let mut arr = match json_response {
Value::Array(arr) => arr,
_ => panic!("Expected JSON array in response"),
};
arr.sort_by(|a, b| a.as_str().cmp(&b.as_str()));
assert_eq!(
arr,
vec![
json!("rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp"),
json!("rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE"),
]
);
}
}
+8 -8
View File
@@ -760,7 +760,7 @@ mod routes {
"closed": 0,
},
"id": RID,
"seeding": 0,
"seeding": 1,
},
{
"name": "again-hello-world",
@@ -788,7 +788,7 @@ mod routes {
"closed": 0,
},
"id": "rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE",
"seeding": 0,
"seeding": 1,
},
])
);
@@ -829,7 +829,7 @@ mod routes {
"closed": 0,
},
"id": RID,
"seeding": 0,
"seeding": 1,
},
{
"name": "again-hello-world",
@@ -857,7 +857,7 @@ mod routes {
"closed": 0,
},
"id": "rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE",
"seeding": 0,
"seeding": 1,
},
])
);
@@ -898,7 +898,7 @@ mod routes {
"closed": 0,
},
"id": RID,
"seeding": 0,
"seeding": 1,
})
);
}
@@ -924,7 +924,7 @@ mod routes {
"alias": CONTRIBUTOR_ALIAS
}
],
"seeds": 0,
"seeds": 1,
},
{
"rid": "rad:z4GypKmh1gkEfmkXtarcYnkvtFUfE",
@@ -937,7 +937,7 @@ mod routes {
"alias": CONTRIBUTOR_ALIAS
},
],
"seeds": 0,
"seeds": 1,
},
])
);
@@ -964,7 +964,7 @@ mod routes {
"alias": CONTRIBUTOR_ALIAS,
}
],
"seeds": 0,
"seeds": 1,
},
])
);
+7 -4
View File
@@ -4,7 +4,7 @@ use axum::routing::get;
use axum::{Json, Router};
use serde_json::json;
use radicle::storage::ReadStorage;
use radicle::node::routing::Store;
use crate::api::error::Error;
use crate::api::Context;
@@ -18,9 +18,12 @@ pub fn router(ctx: Context) -> Router {
/// Return the stats for the node.
/// `GET /stats`
async fn stats_handler(State(ctx): State<Context>) -> impl IntoResponse {
let total = ctx.profile.storage.repositories()?.len();
let db = &ctx.profile.database()?;
let nid = ctx.profile.public_key;
Ok::<_, Error>(Json(json!({ "repos": { "total": total } })))
let total_seeded = db.get_inventory(&nid)?.len();
Ok::<_, Error>(Json(json!({ "repos": { "total": total_seeded } })))
}
#[cfg(test)]
@@ -37,6 +40,6 @@ mod routes {
let response = get(&app, "/stats").await;
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(response.json().await, json!({ "repos": { "total": 3 } }));
assert_eq!(response.json().await, json!({ "repos": { "total": 2 } }));
}
}
+23 -1
View File
@@ -7,6 +7,7 @@ use std::sync::Arc;
use axum::body::{Body, Bytes};
use axum::http::{Method, Request};
use axum::Router;
use radicle::node::{Features, Timestamp, UserAgent};
use serde_json::Value;
use tower::ServiceExt;
@@ -17,8 +18,8 @@ use radicle::git::{raw as git2, RefString};
use radicle::identity::Visibility;
use radicle::profile::{env, Home};
use radicle::storage::ReadStorage;
use radicle::Storage;
use radicle::{node, profile};
use radicle::{Node, Storage};
use radicle_crypto::test::signer::MockSigner;
use crate::api::Context;
@@ -52,6 +53,18 @@ pub fn profile(home: &Path, seed: [u8; 32]) -> radicle::Profile {
let mut db = home.policies_mut().unwrap();
db.follow(&keypair.pk.into(), Some(&alias)).unwrap();
let node_db = home.database_mut().unwrap();
node_db
.init(
&keypair.pk.into(),
Features::SEED,
&alias,
&UserAgent::default(),
Timestamp::try_from(TIMESTAMP).unwrap(),
[],
)
.unwrap();
radicle::storage::git::transport::local::register(storage.clone());
keystore.store(keypair.clone(), "radicle", None).unwrap();
@@ -216,6 +229,11 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
)
.unwrap();
policies.seed(&rid, node::policy::Scope::All).unwrap();
let node_handle = &mut Node::new(profile.socket());
profile
.seed(rid, node::policy::Scope::All, node_handle)
.unwrap();
profile.add_inventory(rid, node_handle).unwrap();
let storage = &profile.storage;
let repo = storage.repository(rid).unwrap();
@@ -291,6 +309,10 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
)
.unwrap();
policies.seed(&rid, node::policy::Scope::Followed).unwrap();
profile
.seed(rid, node::policy::Scope::Followed, node_handle)
.unwrap();
profile.add_inventory(rid, node_handle).unwrap();
let options = crate::Options {
aliases: std::collections::HashMap::new(),