diff --git a/Cargo.lock b/Cargo.lock index c64da9669187120d299c9ad8265e601a924a0fac..1a96b62ec0a40c61587e5eec105ac6929db5237b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,7 +1996,6 @@ name = "slug-types" version = "0.1.0" dependencies = [ "serde", - "serde_json", "url", ] diff --git a/server/src/api/helpers.rs b/server/src/api/helpers.rs index 8cad05bd12d8fe09ad354137dea03efd11466694..2ab25c778ab1ccb02ba5ac2ebef3b7a059203249 100644 --- a/server/src/api/helpers.rs +++ b/server/src/api/helpers.rs @@ -144,23 +144,6 @@ pub fn paginate_rankings( (out_components, out_unranked) } -/// Flatten a paginated global rank page into the `items` list CLI ≤0.0.68 requires. -pub fn flatten_global_rank_items( - components: &[RankComponent], - unranked_items: &[GardenItemUrl], - want_percent: bool, -) -> Vec { - components - .iter() - .flat_map(|component| component.ranking.iter().cloned()) - .chain(unranked_items.iter().map(|item| RankRow { - item: item.clone(), - score: 0.0, - percent: want_percent.then_some(0.0), - })) - .collect() -} - pub fn pick_random_distinct_item_pair(items: &[ItemId]) -> Option<(ItemId, ItemId)> { use rand::seq::SliceRandom; if items.len() < 2 { @@ -268,28 +251,3 @@ pub fn vote_touches_path(content: &ContentState, a: &str, b: &str, parent_canon: let members = content.members_of(&parent); members.iter().any(|m| *m == a || *m == b) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn flatten_global_rank_items_ranked_then_unranked() { - let components = vec![RankComponent { - pairs: 1, - ranking: vec![RankRow { - item: GardenItemUrl("https://slug.social/~/rust".into()), - score: 1.5, - percent: Some(100.0), - }], - }]; - let unranked = vec![GardenItemUrl("https://slug.social/~/go".into())]; - let items = flatten_global_rank_items(&components, &unranked, true); - assert_eq!(items.len(), 2); - assert_eq!(items[0].item.as_str(), "https://slug.social/~/rust"); - assert_eq!(items[0].score, 1.5); - assert_eq!(items[1].item.as_str(), "https://slug.social/~/go"); - assert_eq!(items[1].score, 0.0); - assert_eq!(items[1].percent, Some(0.0)); - } -} diff --git a/server/src/api/rpc.rs b/server/src/api/rpc.rs index 8c70f741f1ea5943fa03df26624021dea1b8a49a..29749c3c757f79f99b6e9acf181b451e844d6e74 100644 --- a/server/src/api/rpc.rs +++ b/server/src/api/rpc.rs @@ -22,9 +22,8 @@ use crate::{ use super::auth::{parse_bearer, verify_bearer_principal}; use super::helpers::{ - compute_connectivity_stats, flatten_global_rank_items, is_pair_voted, now_ms, - paginate_rankings, parse_parent_specs, pick_random_distinct_item_pair, - validate_garden_parent_scope_paths, vote_touches_path, + compute_connectivity_stats, is_pair_voted, now_ms, paginate_rankings, parse_parent_specs, + pick_random_distinct_item_pair, validate_garden_parent_scope_paths, vote_touches_path, }; use super::validate::validate_ingest_document; @@ -1439,7 +1438,6 @@ pub async fn dispatch_rpc(state: &AppState, headers: &HeaderMap, cmd: RpcCommand .collect(); let (components, unranked_items) = paginate_rankings(components, unranked, offset, Some(limit)); - let items = flatten_global_rank_items(&components, &unranked_items, want_percent); line_ok(RpcResult::GlobalRank(GlobalRankResponse { ranked_total, @@ -1448,7 +1446,6 @@ pub async fn dispatch_rpc(state: &AppState, headers: &HeaderMap, cmd: RpcCommand limit, components, unranked_items, - items, })) } } diff --git a/server/tests/integration_rpc.rs b/server/tests/integration_rpc.rs index 935eeee24a639d987cbaf5e5929471c4a0077579..993cf8d386fa071f386260d5923412d0d28664e1 100644 --- a/server/tests/integration_rpc.rs +++ b/server/tests/integration_rpc.rs @@ -264,12 +264,12 @@ async fn test_rank_endpoint() { }]); let global_body = rpc_batch(&client, addr, None, global_batch).await; let global = &global_body["results"][0]["result"]["GlobalRank"]; + assert!(global["components"].is_array()); + assert!(global["unranked_items"].is_array()); assert!( - global["items"].is_array(), - "CLI ≤0.0.68 requires flattened items: {global}" + global.get("items").is_none(), + "GetGlobalRank is components + unranked_items only: {global}" ); - assert!(!global["items"].as_array().unwrap().is_empty()); - assert!(global["components"].is_array()); } #[tokio::test] diff --git a/types/Cargo.toml b/types/Cargo.toml index efdcdfcdc182e501ce079003eb4f0aec474589a8..5dc3becf238f23243313dff0484c682a7b225737 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -6,6 +6,3 @@ edition = "2021" [dependencies] serde = { version = "1.0", features = ["derive"] } url = { version = "2.5", features = ["serde"] } - -[dev-dependencies] -serde_json = "1" diff --git a/types/src/lib.rs b/types/src/lib.rs index 40ac995ab97fe17b795a11f64b000196fa95f075..9a6da984fde1c7c32b57e1df6f4ce0a83868d942 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -55,15 +55,9 @@ pub struct GlobalRankResponse { pub limit: usize, /// Ranked components, ordered largest-first. Scores and percentages are comparable within, /// but not across, components. - #[serde(default)] pub components: Vec, /// Unranked items included in this page after the ranked components. - #[serde(default)] pub unranked_items: Vec, - /// Flattened page for CLI ≤0.0.68: ranked rows first, then unranked at score 0. - /// Always serialized so published clients that require `items` keep working. - #[serde(default)] - pub items: Vec, } #[derive(Debug, Serialize, Deserialize)] @@ -778,64 +772,3 @@ pub struct VoteResponse { pub ranking: Vec, pub next: NextMoves, } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn global_rank_response_deserializes_legacy_items_and_components() { - let legacy = r#"{ - "ranked_total": 1, - "unranked_total": 0, - "offset": 0, - "limit": 25, - "items": [{"item": "https://slug.social/~/rust", "score": 1.0}] - }"#; - let parsed: GlobalRankResponse = serde_json::from_str(legacy).unwrap(); - assert_eq!(parsed.items.len(), 1); - assert!(parsed.components.is_empty()); - assert!(parsed.unranked_items.is_empty()); - - let modern = r#"{ - "ranked_total": 1, - "unranked_total": 1, - "offset": 0, - "limit": 25, - "components": [{"pairs": 1, "ranking": [{"item": "https://slug.social/~/rust", "score": 1.0}]}], - "unranked_items": ["https://slug.social/~/go"] - }"#; - let parsed: GlobalRankResponse = serde_json::from_str(modern).unwrap(); - assert_eq!(parsed.components.len(), 1); - assert_eq!(parsed.unranked_items.len(), 1); - assert!(parsed.items.is_empty()); - } - - #[test] - fn global_rank_response_serializes_items_for_old_cli() { - let resp = GlobalRankResponse { - ranked_total: 1, - unranked_total: 0, - offset: 0, - limit: 25, - components: vec![RankComponent { - pairs: 1, - ranking: vec![RankRow { - item: GardenItemUrl("https://slug.social/~/rust".into()), - score: 1.0, - percent: None, - }], - }], - unranked_items: vec![], - items: vec![RankRow { - item: GardenItemUrl("https://slug.social/~/rust".into()), - score: 1.0, - percent: None, - }], - }; - let json = serde_json::to_value(&resp).unwrap(); - assert!(json.get("items").and_then(|v| v.as_array()).is_some()); - assert_eq!(json["items"].as_array().unwrap().len(), 1); - assert_eq!(json["components"].as_array().unwrap().len(), 1); - } -}