node/debug: Use derived serializers

The construction of the debug object is unwieldy, and error prone
(for example, renamed struct members have to be manually renamed
in the serialization code, see "refs" vs. "refsAt").

Use derived serializers where possible to make this easier to maintain.
This commit is contained in:
Lorenz Leutgeb 2026-02-13 16:14:36 +01:00 committed by Fintan Halpenny
parent a1fa38018e
commit 5099c25df7
3 changed files with 12 additions and 34 deletions

View File

@ -350,35 +350,10 @@ impl radicle::node::Handle for Handle {
fn debug(&self) -> Result<serde_json::Value, Self::Error> { fn debug(&self) -> Result<serde_json::Value, Self::Error> {
let (sender, receiver) = chan::bounded(1); let (sender, receiver) = chan::bounded(1);
let query: Arc<QueryState> = Arc::new(move |state| { let query: Arc<QueryState> = Arc::new(move |state| {
let fetcher_state = state.fetching();
let debug = serde_json::json!({ let debug = serde_json::json!({
"outboxSize": state.outbox().len(), "outboxSize": state.outbox().len(),
"fetching": fetcher_state.active_fetches() "fetching": state.fetching(),
.iter() "rateLimiter": state.limiter(),
.map(|(rid, active)| {
json!({
"rid": rid,
"from": active.from(),
"refsAt": active.refs(),
})
}).collect::<Vec<_>>(),
"queue": fetcher_state.queued_fetches().iter().map(|(node, queue)| {
json!({
"nid": node,
"queue": queue.iter().map(|fetch| {
json!({
"rid": fetch.rid,
"refsAt": fetch.refs,
})
}).collect::<Vec<_>>()
})
}).collect::<Vec<_>>(),
"rateLimiter": state.limiter().buckets.iter().map(|(host, bucket)| {
json!({
"host": host.to_string(),
"bucket": bucket
})
}).collect::<Vec<_>>(),
"events": json!({ "events": json!({
"subscribers": state.emitter().subscriptions(), "subscribers": state.emitter().subscriptions(),
"pending": state.emitter().pending(), "pending": state.emitter().pending(),

View File

@ -10,6 +10,7 @@ pub mod event;
pub use command::Command; pub use command::Command;
pub use event::Event; pub use event::Event;
use serde::Serialize;
use std::collections::{BTreeMap, VecDeque}; use std::collections::{BTreeMap, VecDeque};
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
@ -42,7 +43,7 @@ pub const MAX_CONCURRENCY: NonZeroUsize = NonZeroUsize::MIN;
/// of fetches can happen with it concurrently. This does not guarantee that the /// of fetches can happen with it concurrently. This does not guarantee that the
/// node will actually allow this node to fetch from it since it will maintain /// node will actually allow this node to fetch from it since it will maintain
/// its own capacity for connections and load. /// its own capacity for connections and load.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct FetcherState { pub struct FetcherState {
/// The active fetches that are occurring, ensuring only one fetch per repository. /// The active fetches that are occurring, ensuring only one fetch per repository.
active: BTreeMap<RepoId, ActiveFetch>, active: BTreeMap<RepoId, ActiveFetch>,
@ -235,7 +236,7 @@ impl FetcherState {
} }
/// Configuration for the [`FetcherState`]. /// Configuration for the [`FetcherState`].
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct Config { pub struct Config {
/// Maximum number of concurrent fetches per peer connection. /// Maximum number of concurrent fetches per peer connection.
maximum_concurrency: NonZeroUsize, maximum_concurrency: NonZeroUsize,
@ -271,7 +272,7 @@ impl Default for Config {
} }
/// An active fetch represents a repository being fetched by a particular node. /// An active fetch represents a repository being fetched by a particular node.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct ActiveFetch { pub struct ActiveFetch {
pub from: NodeId, pub from: NodeId,
pub refs: RefsToFetch, pub refs: RefsToFetch,
@ -290,7 +291,7 @@ impl ActiveFetch {
} }
/// A fetch that is waiting to be processed, in the fetch queue. /// A fetch that is waiting to be processed, in the fetch queue.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub struct QueuedFetch { pub struct QueuedFetch {
/// The repository that will be fetched. /// The repository that will be fetched.
pub rid: RepoId, pub rid: RepoId,
@ -304,14 +305,15 @@ pub struct QueuedFetch {
/// ///
/// It ensures that the queue contains unique items for fetching, and does not /// It ensures that the queue contains unique items for fetching, and does not
/// exceed the provided maximum capacity. /// exceed the provided maximum capacity.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct Queue { pub struct Queue {
queue: VecDeque<QueuedFetch>, queue: VecDeque<QueuedFetch>,
max_queue_size: MaxQueueSize, max_queue_size: MaxQueueSize,
} }
/// The maximum number of fetches that can be queued for a single node. /// The maximum number of fetches that can be queued for a single node.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(transparent)]
pub struct MaxQueueSize(usize); pub struct MaxQueueSize(usize);
impl MaxQueueSize { impl MaxQueueSize {

View File

@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
use localtime::LocalTime; use localtime::LocalTime;
use radicle::node::{address, config, HostName, NodeId}; use radicle::node::{address, config, HostName, NodeId};
use serde::Serialize;
/// Peer rate limiter. /// Peer rate limiter.
/// ///
@ -9,7 +10,7 @@ use radicle::node::{address, config, HostName, NodeId};
/// and every request from that address consumes one token. Tokens refill at a predefined /// and every request from that address consumes one token. Tokens refill at a predefined
/// rate. This mechanism allows for consistent request rates with potential bursts up to the /// rate. This mechanism allows for consistent request rates with potential bursts up to the
/// bucket's capacity. /// bucket's capacity.
#[derive(Debug, Default)] #[derive(Debug, Default, Serialize)]
pub struct RateLimiter { pub struct RateLimiter {
pub buckets: HashMap<HostName, TokenBucket>, pub buckets: HashMap<HostName, TokenBucket>,
pub bypass: HashSet<NodeId>, pub bypass: HashSet<NodeId>,