Skip to main content

ic_query/sns/report/model/requests/
metrics.rs

1//! Module: sns::report::model::requests::metrics
2//!
3//! Responsibility: bounded SNS Governance metrics request contract.
4//! Does not own: CLI parsing, discovery, live calls, or rendering.
5//! Boundary: validates the proposal-count window before any source access.
6
7#[cfg(feature = "host")]
8use crate::sns::report::{SnsHostError, SnsLookupRequest};
9
10/// Default recent-proposal window used by SNS metrics reports.
11pub const DEFAULT_SNS_METRICS_TIME_WINDOW_SECONDS: u64 = 30 * 24 * 60 * 60;
12
13/// Largest recent-proposal window accepted by SNS metrics reports.
14pub const MAX_SNS_METRICS_TIME_WINDOW_SECONDS: u64 = 365 * 24 * 60 * 60;
15
16///
17/// SnsMetricsRequest
18///
19/// Request for one bounded SNS Governance metrics report.
20///
21
22#[derive(Clone, Debug, Eq, PartialEq)]
23pub struct SnsMetricsRequest {
24    /// Requested IC network identity.
25    pub network: String,
26    /// IC API endpoint used for discovery and Governance queries.
27    pub source_endpoint: String,
28    /// Caller-supplied collection time in Unix seconds.
29    pub now_unix_secs: u64,
30    /// SNS list id or Root principal.
31    pub input: String,
32    /// Window used for recent submitted/executed proposal counts.
33    pub time_window_seconds: u64,
34}
35
36impl SnsMetricsRequest {
37    /// Construct a request with the default 30-day proposal-count window.
38    #[must_use]
39    pub fn new(
40        network: impl Into<String>,
41        source_endpoint: impl Into<String>,
42        now_unix_secs: u64,
43        input: impl Into<String>,
44    ) -> Self {
45        Self {
46            network: network.into(),
47            source_endpoint: source_endpoint.into(),
48            now_unix_secs,
49            input: input.into(),
50            time_window_seconds: DEFAULT_SNS_METRICS_TIME_WINDOW_SECONDS,
51        }
52    }
53
54    /// Replace the proposal-count window.
55    #[must_use]
56    pub const fn with_time_window_seconds(mut self, time_window_seconds: u64) -> Self {
57        self.time_window_seconds = time_window_seconds;
58        self
59    }
60}
61
62#[cfg(feature = "host")]
63pub(in crate::sns::report) fn validate_sns_metrics_request(
64    request: &SnsMetricsRequest,
65) -> Result<(), SnsHostError> {
66    validate_sns_metrics_time_window(request.time_window_seconds)
67}
68
69#[cfg(feature = "host")]
70pub(in crate::sns::report) fn validate_sns_metrics_time_window(
71    time_window_seconds: u64,
72) -> Result<(), SnsHostError> {
73    if !(1..=MAX_SNS_METRICS_TIME_WINDOW_SECONDS).contains(&time_window_seconds) {
74        return Err(SnsHostError::InvalidMetricsTimeWindow {
75            seconds: time_window_seconds,
76            max_seconds: MAX_SNS_METRICS_TIME_WINDOW_SECONDS,
77        });
78    }
79    Ok(())
80}
81
82#[cfg(feature = "host")]
83pub(in crate::sns::report) fn sns_metrics_lookup_request(
84    request: &SnsMetricsRequest,
85) -> SnsLookupRequest {
86    SnsLookupRequest {
87        network: request.network.clone(),
88        source_endpoint: request.source_endpoint.clone(),
89        now_unix_secs: request.now_unix_secs,
90        input: request.input.clone(),
91    }
92}