LCOV - code coverage report
Current view: top level - libs/pageserver_api/src/models - utilization.rs (source / functions) Coverage Total Hit
Test: 792183ae0ef4f1f8b22e9ac7e8748740ab73f873.info Lines: 100.0 % 24 24
Test Date: 2024-06-26 01:04:33 Functions: 15.8 % 19 3

            Line data    Source code
       1              : use utils::serde_system_time::SystemTime;
       2              : 
       3              : /// Pageserver current utilization and scoring for how good candidate the pageserver would be for
       4              : /// the next tenant.
       5              : ///
       6              : /// See and maintain pageserver openapi spec for `/v1/utilization_score` as the truth.
       7              : ///
       8              : /// `format: int64` fields must use `ser_saturating_u63` because openapi generated clients might
       9              : /// not handle full u64 values properly.
      10            6 : #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
      11              : pub struct PageserverUtilization {
      12              :     /// Used disk space
      13              :     #[serde(serialize_with = "ser_saturating_u63")]
      14              :     pub disk_usage_bytes: u64,
      15              :     /// Free disk space
      16              :     #[serde(serialize_with = "ser_saturating_u63")]
      17              :     pub free_space_bytes: u64,
      18              :     /// Lower is better score for how good candidate for a next tenant would this pageserver be.
      19              :     #[serde(serialize_with = "ser_saturating_u63")]
      20              :     pub utilization_score: u64,
      21              :     /// When was this snapshot captured, pageserver local time.
      22              :     ///
      23              :     /// Use millis to give confidence that the value is regenerated often enough.
      24              :     pub captured_at: SystemTime,
      25              : }
      26              : 
      27              : /// openapi knows only `format: int64`, so avoid outputting a non-parseable value by generated clients.
      28              : ///
      29              : /// Instead of newtype, use this because a newtype would get require handling deserializing values
      30              : /// with the highest bit set which is properly parsed by serde formats, but would create a
      31              : /// conundrum on how to handle and again serialize such values at type level. It will be a few
      32              : /// years until we can use more than `i64::MAX` bytes on a disk.
      33            6 : fn ser_saturating_u63<S: serde::Serializer>(value: &u64, serializer: S) -> Result<S::Ok, S::Error> {
      34            6 :     const MAX_FORMAT_INT64: u64 = i64::MAX as u64;
      35            6 : 
      36            6 :     let value = (*value).min(MAX_FORMAT_INT64);
      37            6 : 
      38            6 :     serializer.serialize_u64(value)
      39            6 : }
      40              : 
      41              : #[cfg(test)]
      42              : mod tests {
      43              :     use std::time::Duration;
      44              : 
      45              :     use super::*;
      46              : 
      47              :     #[test]
      48            2 :     fn u64_max_is_serialized_as_u63_max() {
      49            2 :         let doc = PageserverUtilization {
      50            2 :             disk_usage_bytes: u64::MAX,
      51            2 :             free_space_bytes: 0,
      52            2 :             utilization_score: u64::MAX,
      53            2 :             captured_at: SystemTime(
      54            2 :                 std::time::SystemTime::UNIX_EPOCH + Duration::from_secs(1708509779),
      55            2 :             ),
      56            2 :         };
      57            2 : 
      58            2 :         let s = serde_json::to_string(&doc).unwrap();
      59            2 : 
      60            2 :         let expected = r#"{"disk_usage_bytes":9223372036854775807,"free_space_bytes":0,"utilization_score":9223372036854775807,"captured_at":"2024-02-21T10:02:59.000Z"}"#;
      61            2 : 
      62            2 :         assert_eq!(s, expected);
      63            2 :     }
      64              : }
        

Generated by: LCOV version 2.1-beta