From aefb53cdd992e5e6d5cd086f51bddde7e36ab3fd Mon Sep 17 00:00:00 2001 From: Nikhil Sinha Date: Fri, 19 Jun 2026 17:22:57 +0700 Subject: [PATCH 1/2] add optional ingestion quota to tenant metadata --- src/storage/mod.rs | 3 ++- src/storage/store_metadata.rs | 28 ++++++++++++++++++++++++++++ src/tenants/mod.rs | 9 ++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/storage/mod.rs b/src/storage/mod.rs index e40100195..ac010edf6 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -93,7 +93,8 @@ pub use localfs::FSConfig; pub use object_storage::{ObjectStorage, ObjectStorageProvider}; pub use s3::S3Config; pub use store_metadata::{ - StorageMetadata, put_remote_metadata, put_staging_metadata, resolve_parseable_metadata, + IngestionQuota, IngestionQuotaType, QuotaPeriod, StorageMetadata, put_remote_metadata, + put_staging_metadata, resolve_parseable_metadata, }; // metadata file names in a Stream prefix diff --git a/src/storage/store_metadata.rs b/src/storage/store_metadata.rs index a04008a61..71a308317 100644 --- a/src/storage/store_metadata.rs +++ b/src/storage/store_metadata.rs @@ -52,6 +52,28 @@ pub struct StaticStorageMetadata { } // Type for serialization and deserialization +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct IngestionQuota { + #[serde(rename = "type")] + pub quota_type: IngestionQuotaType, + pub limit: u64, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum IngestionQuotaType { + SizeBytes, + EventCount, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum QuotaPeriod { + Monthly, + Yearly, + Lifetime, +} + #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct StorageMetadata { pub version: String, @@ -79,6 +101,10 @@ pub struct StorageMetadata { #[serde(default, skip_serializing_if = "Option::is_none")] pub plan: Option, #[serde(default, skip_serializing_if = "Option::is_none")] + pub ingestion_quota: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub quota_period: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] pub owner: Option, } @@ -102,6 +128,8 @@ impl Default for StorageMetadata { start_date: None, end_date: None, plan: None, + ingestion_quota: None, + quota_period: None, owner: None, } } diff --git a/src/tenants/mod.rs b/src/tenants/mod.rs index 442c44c3b..a647b094c 100644 --- a/src/tenants/mod.rs +++ b/src/tenants/mod.rs @@ -23,7 +23,10 @@ use itertools::Itertools; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use crate::{rbac::role::Action, storage::StorageMetadata}; +use crate::{ + rbac::role::Action, + storage::{IngestionQuota, QuotaPeriod, StorageMetadata}, +}; pub static TENANT_METADATA: Lazy> = Lazy::new(|| Arc::new(TenantMetadata::default())); @@ -70,12 +73,16 @@ impl TenantMetadata { start_date: Option, end_date: Option, plan: Option, + ingestion_quota: Option, + quota_period: Option, ) -> bool { if let Some(mut tenant) = self.tenants.get_mut(tenant_id) { tenant.meta.customer_name = customer_name; tenant.meta.start_date = start_date; tenant.meta.end_date = end_date; tenant.meta.plan = plan; + tenant.meta.ingestion_quota = ingestion_quota; + tenant.meta.quota_period = quota_period; true } else { false From e9a80203a8df3e947bd97911944cbdbc43bba5c6 Mon Sep 17 00:00:00 2001 From: Nikhil Sinha Date: Sat, 20 Jun 2026 23:11:51 +0700 Subject: [PATCH 2/2] clippy fix --- src/tenants/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tenants/mod.rs b/src/tenants/mod.rs index a647b094c..e0c983203 100644 --- a/src/tenants/mod.rs +++ b/src/tenants/mod.rs @@ -66,6 +66,7 @@ impl TenantMetadata { self.tenants.get(tenant_id).map(|t| t.meta.clone()) } + #[allow(clippy::too_many_arguments)] pub fn update_tenant_meta( &self, tenant_id: &str,