Skip to content

Commit a6bbf7a

Browse files
committed
share timeout const
1 parent 6abfee0 commit a6bbf7a

3 files changed

Lines changed: 13 additions & 4 deletions

File tree

apps/sim/lib/billing/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ export const SEARCH_TOOL_COST = 0.01
3434
*/
3535
export const DEFAULT_OVERAGE_THRESHOLD = 100
3636

37+
/**
38+
* Maximum time to wait on billing coordination row locks before retrying later.
39+
*/
40+
export const BILLING_LOCK_TIMEOUT_MS = 5_000
41+
3742
/**
3843
* Available credit tiers. Each tier maps a credit amount to the underlying dollar cost.
3944
* 1 credit = $0.005, so credits = dollars * 200.

apps/sim/lib/billing/threshold-billing.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { db } from '@sim/db'
22
import { member, organization, subscription, userStats } from '@sim/db/schema'
33
import { createLogger } from '@sim/logger'
44
import { and, eq, sql } from 'drizzle-orm'
5-
import { DEFAULT_OVERAGE_THRESHOLD } from '@/lib/billing/constants'
5+
import { BILLING_LOCK_TIMEOUT_MS, DEFAULT_OVERAGE_THRESHOLD } from '@/lib/billing/constants'
66
import { getEffectiveBillingStatus, isOrganizationBillingBlocked } from '@/lib/billing/core/access'
77
import { calculateSubscriptionOverage, computeOrgOverageAmount } from '@/lib/billing/core/billing'
88
import {
@@ -22,7 +22,6 @@ import { enqueueOutboxEvent } from '@/lib/core/outbox/service'
2222
const logger = createLogger('ThresholdBilling')
2323

2424
const OVERAGE_THRESHOLD = envNumber(env.OVERAGE_THRESHOLD_DOLLARS, DEFAULT_OVERAGE_THRESHOLD)
25-
const USER_STATS_LOCK_TIMEOUT_MS = 5_000
2625
const USAGE_TOTAL_EPSILON = 0.000001
2726

2827
interface PersonalUsageSnapshot {
@@ -119,7 +118,7 @@ export async function checkAndBillOverageThreshold(userId: string): Promise<void
119118
const totalOverageCents = Math.round(currentOverage * 100)
120119

121120
await db.transaction(async (tx) => {
122-
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${USER_STATS_LOCK_TIMEOUT_MS}ms'`))
121+
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${BILLING_LOCK_TIMEOUT_MS}ms'`))
123122

124123
const statsRecords = await tx
125124
.select()
@@ -363,7 +362,7 @@ async function checkAndBillOrganizationOverageThreshold(organizationId: string):
363362
const totalOverageCents = Math.round(currentOverage * 100)
364363

365364
await db.transaction(async (tx) => {
366-
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${USER_STATS_LOCK_TIMEOUT_MS}ms'`))
365+
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${BILLING_LOCK_TIMEOUT_MS}ms'`))
367366

368367
const lockedOwnerRows = await tx
369368
.select({ userId: member.userId })

apps/sim/lib/billing/webhooks/invoices.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { createLogger } from '@sim/logger'
1111
import { and, eq, inArray, isNull, ne, or, sql } from 'drizzle-orm'
1212
import type Stripe from 'stripe'
1313
import { getEmailSubject, PaymentFailedEmail, renderCreditPurchaseEmail } from '@/components/emails'
14+
import { BILLING_LOCK_TIMEOUT_MS } from '@/lib/billing/constants'
1415
import { calculateSubscriptionOverage, isSubscriptionOrgScoped } from '@/lib/billing/core/billing'
1516
import { addCredits, getCreditBalanceForEntity } from '@/lib/billing/credits/balance'
1617
import { setUsageLimitForCredits } from '@/lib/billing/credits/purchase'
@@ -389,6 +390,8 @@ export async function getBilledOverageForSubscription(sub: {
389390
export async function resetUsageForSubscription(sub: { plan: string | null; referenceId: string }) {
390391
if (await isSubscriptionOrgScoped(sub)) {
391392
await db.transaction(async (tx) => {
393+
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${BILLING_LOCK_TIMEOUT_MS}ms'`))
394+
392395
const ownerRows = await tx
393396
.select({ userId: member.userId })
394397
.from(member)
@@ -907,6 +910,8 @@ export async function handleInvoiceFinalized(event: Stripe.Event) {
907910
// then lock the tracker row so `billedOverageThisPeriod` is serialized
908911
// against threshold billing, resets, owner transfers, and retries.
909912
const phase1 = await db.transaction(async (tx) => {
913+
await tx.execute(sql.raw(`SET LOCAL lock_timeout = '${BILLING_LOCK_TIMEOUT_MS}ms'`))
914+
910915
let trackerUserId = entityId
911916
if (entityType === 'organization') {
912917
const ownerRows = await tx

0 commit comments

Comments
 (0)