Skip to content

Commit 6e58594

Browse files
committed
Don't create a new block if the previous one's 5 hours is not up
1 parent 05b0321 commit 6e58594

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

packages/billing/src/subscription.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,25 @@ export interface WeeklyLimitError {
6363
resetsAt: Date
6464
}
6565

66-
export type BlockGrantResult = BlockGrant | WeeklyLimitError
66+
export interface BlockExhaustedError {
67+
error: 'block_exhausted'
68+
blockUsed: number
69+
blockLimit: number
70+
resetsAt: Date
71+
}
72+
73+
export type BlockGrantResult = BlockGrant | WeeklyLimitError | BlockExhaustedError
6774

6875
export function isWeeklyLimitError(
6976
result: BlockGrantResult,
7077
): result is WeeklyLimitError {
71-
return 'error' in result
78+
return 'error' in result && result.error === 'weekly_limit_reached'
79+
}
80+
81+
export function isBlockExhaustedError(
82+
result: BlockGrantResult,
83+
): result is BlockExhaustedError {
84+
return 'error' in result && result.error === 'block_exhausted'
7285
}
7386

7487
export interface RateLimitStatus {
@@ -251,7 +264,7 @@ export async function ensureActiveBlockGrantCallback(params: {
251264
const { conn, userId, subscription, logger, now = new Date() } = params
252265
const subscriptionId = subscription.stripe_subscription_id
253266

254-
// 1. Check for an existing active block grant
267+
// 1. Check for an existing non-expired block grant (regardless of balance)
255268
const existingGrants = await conn
256269
.select()
257270
.from(schema.creditLedger)
@@ -260,20 +273,31 @@ export async function ensureActiveBlockGrantCallback(params: {
260273
eq(schema.creditLedger.user_id, userId),
261274
eq(schema.creditLedger.type, 'subscription'),
262275
gt(schema.creditLedger.expires_at, now),
263-
gt(schema.creditLedger.balance, 0),
264276
),
265277
)
266278
.orderBy(desc(schema.creditLedger.expires_at))
267279
.limit(1)
268280

269281
if (existingGrants.length > 0) {
270282
const g = existingGrants[0]
283+
284+
// Block exists with credits remaining - return it
285+
if (g.balance > 0) {
286+
return {
287+
grantId: g.operation_id,
288+
credits: g.balance,
289+
expiresAt: g.expires_at!,
290+
isNew: false,
291+
} satisfies BlockGrant
292+
}
293+
294+
// Block exists but is exhausted - don't create a new one until it expires
271295
return {
272-
grantId: g.operation_id,
273-
credits: g.balance,
274-
expiresAt: g.expires_at!,
275-
isNew: false,
276-
} satisfies BlockGrant
296+
error: 'block_exhausted',
297+
blockUsed: g.principal,
298+
blockLimit: g.principal,
299+
resetsAt: g.expires_at!,
300+
} satisfies BlockExhaustedError
277301
}
278302

279303
// 2. Resolve limits

0 commit comments

Comments
 (0)