fix(keys): add DB fallback to updateEmailByCustomer, updateKeyEmail, and recover route (BUG-108, BUG-109, BUG-110)
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m8s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m8s
- updateEmailByCustomer: DB fallback when stripe_customer_id not in cache - updateKeyEmail: DB fallback when key not in cache - POST /v1/recover: DB fallback when email not in cache (was only on verify) - 6 TDD tests added (keys-email-update.test.ts, recover-initial-db-fallback.test.ts) - 547 tests total, all passing
This commit is contained in:
parent
424a16ed8a
commit
d376d586fe
4 changed files with 286 additions and 4 deletions
|
|
@ -186,16 +186,72 @@ export function getAllKeys(): ApiKey[] {
|
|||
|
||||
export async function updateKeyEmail(apiKey: string, newEmail: string): Promise<boolean> {
|
||||
const entry = keysCache.find((k) => k.key === apiKey);
|
||||
if (!entry) return false;
|
||||
entry.email = newEmail;
|
||||
if (entry) {
|
||||
entry.email = newEmail;
|
||||
await queryWithRetry("UPDATE api_keys SET email = $1 WHERE key = $2", [newEmail, apiKey]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// DB fallback: key may exist on another pod's cache or after a restart
|
||||
logger.info({ apiKey: apiKey.slice(0, 10) + "..." }, "updateKeyEmail: cache miss, falling back to DB");
|
||||
const result = await queryWithRetry(
|
||||
"SELECT key, tier, email, created_at, stripe_customer_id FROM api_keys WHERE key = $1 LIMIT 1",
|
||||
[apiKey]
|
||||
);
|
||||
if (result.rows.length === 0) {
|
||||
logger.warn({ apiKey: apiKey.slice(0, 10) + "..." }, "updateKeyEmail: key not found in cache or DB");
|
||||
return false;
|
||||
}
|
||||
|
||||
const row = result.rows[0];
|
||||
await queryWithRetry("UPDATE api_keys SET email = $1 WHERE key = $2", [newEmail, apiKey]);
|
||||
|
||||
// Hydrate local cache
|
||||
const cached: ApiKey = {
|
||||
key: row.key,
|
||||
tier: row.tier as "free" | "pro",
|
||||
email: newEmail,
|
||||
createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
|
||||
stripeCustomerId: row.stripe_customer_id || undefined,
|
||||
};
|
||||
keysCache.push(cached);
|
||||
|
||||
logger.info({ apiKey: apiKey.slice(0, 10) + "..." }, "updateKeyEmail: updated via DB fallback");
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function updateEmailByCustomer(stripeCustomerId: string, newEmail: string): Promise<boolean> {
|
||||
const entry = keysCache.find(k => k.stripeCustomerId === stripeCustomerId);
|
||||
if (!entry) return false;
|
||||
entry.email = newEmail;
|
||||
if (entry) {
|
||||
entry.email = newEmail;
|
||||
await queryWithRetry("UPDATE api_keys SET email = $1 WHERE stripe_customer_id = $2", [newEmail, stripeCustomerId]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// DB fallback: key may exist on another pod's cache or after a restart
|
||||
logger.info({ stripeCustomerId }, "updateEmailByCustomer: 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 }, "updateEmailByCustomer: customer not found in cache or DB");
|
||||
return false;
|
||||
}
|
||||
|
||||
const row = result.rows[0];
|
||||
await queryWithRetry("UPDATE api_keys SET email = $1 WHERE stripe_customer_id = $2", [newEmail, stripeCustomerId]);
|
||||
|
||||
// Hydrate local cache
|
||||
const cached: ApiKey = {
|
||||
key: row.key,
|
||||
tier: row.tier as "free" | "pro",
|
||||
email: newEmail,
|
||||
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 }, "updateEmailByCustomer: updated via DB fallback");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue