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");
}
}
}