Fix billing setup

This commit is contained in:
Jai A 2025-04-03 15:44:53 -07:00
parent 41b9729b9b
commit d0d0dcf09f
No known key found for this signature in database
GPG Key ID: 9A9F9B7250E9883C
3 changed files with 15 additions and 9 deletions

View File

@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT\n id, user_id, price_id, amount, currency_code, status, due, last_attempt,\n charge_type, subscription_id,\n -- Workaround for https://github.com/launchbadge/sqlx/issues/3336\n subscription_interval AS \"subscription_interval?\",\n payment_platform,\n payment_platform_id AS \"payment_platform_id?\",\n parent_charge_id AS \"parent_charge_id?\",\n net AS \"net?\"\n FROM charges\n \n WHERE\n charge_type = $1 AND\n (\n (status = 'open' AND due < NOW()) OR\n (status = 'failed' AND last_attempt < NOW() - INTERVAL '2 days')\n )\n ", "query": "\n SELECT\n id, user_id, price_id, amount, currency_code, status, due, last_attempt,\n charge_type, subscription_id,\n -- Workaround for https://github.com/launchbadge/sqlx/issues/3336\n subscription_interval AS \"subscription_interval?\",\n payment_platform,\n payment_platform_id AS \"payment_platform_id?\",\n parent_charge_id AS \"parent_charge_id?\",\n net AS \"net?\"\n FROM charges\n \n WHERE\n charge_type = $1 AND\n (\n (status = 'open' AND due < NOW()) OR\n (status = 'failed' AND last_attempt < NOW() - INTERVAL '2 days')\n )\n FOR UPDATE SKIP LOCKED\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -102,5 +102,5 @@
true true
] ]
}, },
"hash": "8f51f552d1c63fa818cbdba581691e97f693a187ed05224a44adeee68c6809d1" "hash": "6cd0cfece6d87d039bb22379045509824d2c9eee5e1864a15186e713394f5926"
} }

View File

@ -206,8 +206,8 @@ impl ChargeItem {
Ok(res.and_then(|r| r.try_into().ok())) Ok(res.and_then(|r| r.try_into().ok()))
} }
pub async fn get_chargeable( pub async fn get_chargeable_lock(
exec: impl sqlx::Executor<'_, Database = sqlx::Postgres>, transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Vec<ChargeItem>, DatabaseError> { ) -> Result<Vec<ChargeItem>, DatabaseError> {
let charge_type = ChargeType::Subscription.as_str(); let charge_type = ChargeType::Subscription.as_str();
let res = select_charges_with_predicate!( let res = select_charges_with_predicate!(
@ -218,10 +218,11 @@ impl ChargeItem {
(status = 'open' AND due < NOW()) OR (status = 'open' AND due < NOW()) OR
(status = 'failed' AND last_attempt < NOW() - INTERVAL '2 days') (status = 'failed' AND last_attempt < NOW() - INTERVAL '2 days')
) )
FOR UPDATE SKIP LOCKED
"#, "#,
charge_type charge_type
) )
.fetch_all(exec) .fetch_all(&mut **transaction)
.await?; .await?;
Ok(res Ok(res

View File

@ -2271,9 +2271,11 @@ pub async fn index_billing(
info!("Indexing billing queue"); info!("Indexing billing queue");
let res = async { let res = async {
// If a charge is open and due or has been attempted more than two days ago, it should be processed // If a charge is open and due or has been attempted more than two days ago, it should be processed
let mut transaction = pool.begin().await?;
let charges_to_do = let charges_to_do =
crate::database::models::charge_item::ChargeItem::get_chargeable( crate::database::models::charge_item::ChargeItem::get_chargeable_lock(
&pool, &mut transaction,
) )
.await?; .await?;
@ -2396,8 +2398,11 @@ pub async fn index_billing(
charge.status = ChargeStatus::Processing; charge.status = ChargeStatus::Processing;
stripe::PaymentIntent::create(&stripe_client, intent) if let Err(e) = stripe::PaymentIntent::create(&stripe_client, intent).await {
.await?; tracing::error!("Failed to create payment intent: {:?}", e);
charge.status = ChargeStatus::Failed;
charge.last_attempt = Some(Utc::now());
}
} else { } else {
charge.status = ChargeStatus::Failed; charge.status = ChargeStatus::Failed;
charge.last_attempt = Some(Utc::now()); charge.last_attempt = Some(Utc::now());