use std::collections::BTreeMap;
use crate::{MeteredDoor, Servable, TenantOwner, Usage};
pub mod order {
pub const ENTITLEMENT: &str = "entitlement";
pub const ADD_PRINCIPAL: &str = "add_principal";
pub const TAKEN: &str = "taken";
pub const ADD_USERS: &str = "add_users";
pub const GROW_ROOM: &str = "grow_room";
pub const PURGE_TENANT: &str = "purge_tenant";
pub const GROW_GO_AHEAD: &str = "grow_go_ahead";
pub const SIGN_IN_AGAIN: &str = "sign_in_again";
pub const REFEED: &str = "refeed";
pub const CORE: [&str; 8] = [ENTITLEMENT, ADD_PRINCIPAL, ADD_USERS, GROW_ROOM, PURGE_TENANT, GROW_GO_AHEAD, SIGN_IN_AGAIN, REFEED];
}
pub mod ask {
pub const GROW_SET: &str = "grow_set";
pub const FETCH: &str = "fetch";
pub const CORE: [&str; 2] = [GROW_SET, FETCH];
}
pub fn is_core(kind: &str) -> bool {
order::CORE.contains(&kind) || ask::CORE.contains(&kind)
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct PurgeTenant {
pub tenant: String,
pub reason: String,
pub job: String,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct PurgeAnswer {
pub job: String,
pub running: bool,
pub failed: bool,
pub error: String,
pub detail: String,
pub bytes_reclaimed: Option<u64>,
pub still_locked: bool,
pub failures: Vec<String>,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct AddUsers {
pub tenant: String,
pub ask: crate::UsersAsk,
pub order: String,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct GrowRoom {
pub need_bytes: u64,
pub reason: String,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct AccountRoom {
pub unused_bytes: Option<u64>,
pub room_bytes: u64,
pub seats: u32,
pub seats_open: u32,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct ProductReport {
pub tenants: Vec<TenantOwner>,
pub usage: BTreeMap<String, Usage>,
pub servable: Option<Servable>,
pub metered: Option<MeteredDoor>,
pub room: BTreeMap<String, u64>,
pub promised: BTreeMap<String, BTreeMap<String, u64>>,
pub with_iron: Option<String>,
pub names: Vec<String>,
pub accounts: BTreeMap<String, AccountRoom>,
pub activity: BTreeMap<String, crate::Activity>,
pub measured_unix_ms: u64,
}
pub const ACTIVITY_DAYS: u64 = 30;
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct AddPrincipal {
pub username: String,
pub kind: String,
pub signup: String,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct ProductOrder {
pub params: BTreeMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fetch: Option<Fetch>,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct Fetch {
pub id: String,
pub bytes: u64,
pub param: String,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct FetchAsk {
pub id: String,
}
#[cfg(test)]
mod core_kinds_tests {
use super::{ask, is_core, order};
#[test]
fn the_core_kinds_are_eight_orders_and_two_asks_in_one_list() {
let mut orders = order::CORE.to_vec();
orders.sort_unstable();
orders.dedup();
assert_eq!(orders.len(), 8, "eight distinct core orders");
assert_eq!(order::CORE, [order::ENTITLEMENT, order::ADD_PRINCIPAL, order::ADD_USERS, order::GROW_ROOM, order::PURGE_TENANT, order::GROW_GO_AHEAD, order::SIGN_IN_AGAIN, order::REFEED]);
assert_eq!(ask::CORE, [ask::GROW_SET, ask::FETCH]);
for k in order::CORE.iter().chain(ask::CORE.iter()) {
assert!(is_core(k), "{k} is core");
}
for k in ["recharge_from_twin", "fence_primary", "adopt_twin", "review_twin", "restate_entitlements", "join_member", ""] {
assert!(!is_core(k), "{k:?} is not a core kind");
}
}
}