fix(BUG-106): DB fallback for downgradeByCustomer and recover route
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m7s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m7s
- downgradeByCustomer now queries DB when key not in memory cache, preventing cancelled customers from keeping Pro access in multi-pod setups - recover/verify endpoint falls back to DB lookup when cache miss on email - Added TDD tests for both fallback paths (4 new tests)
This commit is contained in:
parent
4473641ee1
commit
b964b98a8b
4 changed files with 240 additions and 2 deletions
|
|
@ -134,7 +134,33 @@ export async function downgradeByCustomer(stripeCustomerId: string): Promise<boo
|
|||
await queryWithRetry("UPDATE api_keys SET tier = 'free' WHERE stripe_customer_id = $1", [stripeCustomerId]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// DB fallback: key may exist on another pod's cache or after a restart
|
||||
logger.info({ stripeCustomerId }, "downgradeByCustomer: cache miss, falling back to DB");
|
||||
const result = await queryWithRetry(
|
||||
"SELECT key, tier, email, created_at, stripe_customer_id FROM api_keys WHERE stripe_customer_id = $1 LIMIT 1",
|
||||
[stripeCustomerId]
|
||||
);
|
||||
if (result.rows.length === 0) {
|
||||
logger.warn({ stripeCustomerId }, "downgradeByCustomer: customer not found in cache or DB");
|
||||
return false;
|
||||
}
|
||||
|
||||
const row = result.rows[0];
|
||||
await queryWithRetry("UPDATE api_keys SET tier = 'free' WHERE stripe_customer_id = $1", [stripeCustomerId]);
|
||||
|
||||
// Add to local cache so subsequent lookups on this pod work
|
||||
const cached: ApiKey = {
|
||||
key: row.key,
|
||||
tier: "free",
|
||||
email: row.email,
|
||||
createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
|
||||
stripeCustomerId: row.stripe_customer_id || undefined,
|
||||
};
|
||||
keysCache.push(cached);
|
||||
|
||||
logger.info({ stripeCustomerId, key: row.key }, "downgradeByCustomer: downgraded via DB fallback");
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function findKeyByCustomerId(stripeCustomerId: string): Promise<ApiKey | null> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue