collab: Use StripeClient for creating model usage meter events (#31633)

This PR updates the `StripeBilling::bill_model_request_usage` method to
use the `StripeClient` trait.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-05-28 18:19:43 -04:00 committed by GitHub
parent a1c645e57e
commit 469824c350
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 119 additions and 77 deletions

View file

@ -7,11 +7,20 @@ use parking_lot::Mutex;
use uuid::Uuid;
use crate::stripe_client::{
CreateCustomerParams, StripeClient, StripeCustomer, StripeCustomerId, StripeMeter,
StripeMeterId, StripePrice, StripePriceId, StripeSubscription, StripeSubscriptionId,
UpdateSubscriptionParams,
CreateCustomerParams, StripeClient, StripeCreateMeterEventParams, StripeCustomer,
StripeCustomerId, StripeMeter, StripeMeterId, StripePrice, StripePriceId, StripeSubscription,
StripeSubscriptionId, UpdateSubscriptionParams,
};
#[derive(Debug, Clone)]
pub struct StripeCreateMeterEventCall {
pub identifier: Arc<str>,
pub event_name: Arc<str>,
pub value: u64,
pub stripe_customer_id: StripeCustomerId,
pub timestamp: Option<i64>,
}
pub struct FakeStripeClient {
pub customers: Arc<Mutex<HashMap<StripeCustomerId, StripeCustomer>>>,
pub subscriptions: Arc<Mutex<HashMap<StripeSubscriptionId, StripeSubscription>>>,
@ -19,6 +28,7 @@ pub struct FakeStripeClient {
Arc<Mutex<Vec<(StripeSubscriptionId, UpdateSubscriptionParams)>>>,
pub prices: Arc<Mutex<HashMap<StripePriceId, StripePrice>>>,
pub meters: Arc<Mutex<HashMap<StripeMeterId, StripeMeter>>>,
pub create_meter_event_calls: Arc<Mutex<Vec<StripeCreateMeterEventCall>>>,
}
impl FakeStripeClient {
@ -29,6 +39,7 @@ impl FakeStripeClient {
update_subscription_calls: Arc::new(Mutex::new(Vec::new())),
prices: Arc::new(Mutex::new(HashMap::default())),
meters: Arc::new(Mutex::new(HashMap::default())),
create_meter_event_calls: Arc::new(Mutex::new(Vec::new())),
}
}
}
@ -94,4 +105,18 @@ impl StripeClient for FakeStripeClient {
Ok(meters)
}
async fn create_meter_event(&self, params: StripeCreateMeterEventParams<'_>) -> Result<()> {
self.create_meter_event_calls
.lock()
.push(StripeCreateMeterEventCall {
identifier: params.identifier.into(),
event_name: params.event_name.into(),
value: params.payload.value,
stripe_customer_id: params.payload.stripe_customer_id.clone(),
timestamp: params.timestamp,
});
Ok(())
}
}

View file

@ -1,7 +1,7 @@
use std::str::FromStr as _;
use std::sync::Arc;
use anyhow::{Context as _, Result};
use anyhow::{Context as _, Result, anyhow};
use async_trait::async_trait;
use serde::Serialize;
use stripe::{
@ -12,9 +12,10 @@ use stripe::{
};
use crate::stripe_client::{
CreateCustomerParams, StripeClient, StripeCustomer, StripeCustomerId, StripeMeter, StripePrice,
StripePriceId, StripePriceRecurring, StripeSubscription, StripeSubscriptionId,
StripeSubscriptionItem, StripeSubscriptionItemId, UpdateSubscriptionParams,
CreateCustomerParams, StripeClient, StripeCreateMeterEventParams, StripeCustomer,
StripeCustomerId, StripeMeter, StripePrice, StripePriceId, StripePriceRecurring,
StripeSubscription, StripeSubscriptionId, StripeSubscriptionItem, StripeSubscriptionItemId,
UpdateSubscriptionParams,
};
pub struct RealStripeClient {
@ -129,6 +130,26 @@ impl StripeClient for RealStripeClient {
Ok(response.data)
}
async fn create_meter_event(&self, params: StripeCreateMeterEventParams<'_>) -> Result<()> {
let identifier = params.identifier;
match self.client.post_form("/billing/meter_events", params).await {
Ok(event) => Ok(event),
Err(stripe::StripeError::Stripe(error)) => {
if error.http_status == 400
&& error
.message
.as_ref()
.map_or(false, |message| message.contains(identifier))
{
Ok(())
} else {
Err(anyhow!(stripe::StripeError::Stripe(error)))
}
}
Err(error) => Err(anyhow!(error)),
}
}
}
impl From<CustomerId> for StripeCustomerId {