Skip to main content

hashgraph_like_consensus/
service_stats.rs

1//! Scope-level statistics for monitoring consensus activity.
2
3use crate::{
4    events::ConsensusEventBus, scope::ConsensusScope, service::ConsensusService,
5    session::ConsensusState, signing::ConsensusSignatureScheme, storage::ConsensusStorage,
6};
7
8/// Aggregate counters for all sessions within a single scope.
9#[derive(Debug, Clone)]
10pub struct ConsensusStats {
11    /// Total number of proposals in this scope.
12    pub total_sessions: usize,
13    /// How many proposals are still accepting votes.
14    pub active_sessions: usize,
15    /// How many proposals failed to reach consensus (timeout with insufficient votes).
16    pub failed_sessions: usize,
17    /// How many proposals successfully reached consensus.
18    pub consensus_reached: usize,
19}
20
21impl<Scope, Storage, Event, Signer> ConsensusService<Scope, Storage, Event, Signer>
22where
23    Scope: ConsensusScope,
24    Storage: ConsensusStorage<Scope>,
25    Event: ConsensusEventBus<Scope>,
26    Signer: ConsensusSignatureScheme,
27{
28    /// Get statistics about proposals in a scope.
29    ///
30    /// Returns counts of total, active, failed, and finalized proposals.
31    /// Useful for monitoring and dashboards.
32    pub async fn get_scope_stats(&self, scope: &Scope) -> ConsensusStats {
33        self.list_scope_sessions(scope)
34            .await
35            .map(|scope_sessions| {
36                let total_sessions = scope_sessions.len();
37                let active_sessions = scope_sessions.iter().filter(|s| s.is_active()).count();
38                let consensus_reached = scope_sessions
39                    .iter()
40                    .filter(|s| matches!(s.state, ConsensusState::ConsensusReached(_)))
41                    .count();
42                let failed_sessions = scope_sessions
43                    .iter()
44                    .filter(|s| matches!(s.state, ConsensusState::Failed))
45                    .count();
46
47                ConsensusStats {
48                    total_sessions,
49                    active_sessions,
50                    consensus_reached,
51                    failed_sessions,
52                }
53            })
54            .unwrap_or(ConsensusStats {
55                total_sessions: 0,
56                active_sessions: 0,
57                consensus_reached: 0,
58                failed_sessions: 0,
59            })
60    }
61}