Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions svc/api/keyManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,18 @@ keys
api_key,
ip,
concat(date_part('year', timestamp), '-', date_part('month', timestamp)) as month,
date_trunc('month', timestamp) as month_start,
MAX(usage_count) as usage_count
FROM api_key_usage
WHERE
timestamp >= ?
AND timestamp <= ?
AND account_id = ?
GROUP BY account_id, api_key, ip, month
GROUP BY account_id, api_key, ip, month, month_start
) as T1
GROUP BY account_id, month
ORDER BY month DESC
GROUP BY account_id, month, month_start
-- "month" is an unpadded string (e.g. 2026-9), which sorts lexicographically (2026-9 > 2026-10), so order by the real date
ORDER BY month_start DESC
`,
[
moment.utc().subtract(5, "month").startOf("month"),
Expand Down
14 changes: 10 additions & 4 deletions svc/apiadmin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ await runInLoop(
);
continue;
}
// Use UTC: usage rows are bucketed by moment.utc().startOf("month") in web.ts,
// so a non-UTC server timezone would otherwise select the wrong month near boundaries
const startTime = moment
.unix(sub.current_period_end - 1)
.utc()
.startOf("month");
const endTime = moment.unix(sub.current_period_end - 1).endOf("month");
const endTime = moment
.unix(sub.current_period_end - 1)
.utc()
.endOf("month");
const res = await db.raw(
`
SELECT
Expand All @@ -45,10 +51,10 @@ await runInLoop(
api_key_usage.api_key,
api_key_usage.ip,
MAX(api_key_usage.usage_count) as usage
FROM api_key_usage, api_keys
FROM api_key_usage
JOIN api_keys ON api_key_usage.api_key = api_keys.api_key
WHERE
api_key_usage.account_id = api_keys.account_id
AND timestamp >= ?
timestamp >= ?
AND timestamp <= ?
AND subscription_id = ?
GROUP BY api_key_usage.api_key, api_key_usage.ip
Expand Down
8 changes: 7 additions & 1 deletion svc/syncSubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ await runInLoop(async function doSyncSubs() {
// Reconcile, insert any missing subscribers
const accountId = sub.metadata['account_id'];
if (accountId) {
await trx.raw("INSERT INTO subscriber(account_id, customer_id, status) VALUES (?, ?, 'active') ON CONFLICT DO NOTHING", [Number(accountId), sub.customer]);
// If the account already has a row (e.g. from an earlier subscription under a different Stripe customer),
// point it at the customer with the active subscription, otherwise the UPDATE below matches nothing
// and a paying user stays inactive
await trx.raw(
"INSERT INTO subscriber(account_id, customer_id, status) VALUES (?, ?, 'active') ON CONFLICT (account_id) DO UPDATE SET customer_id = EXCLUDED.customer_id, status = 'active'",
[Number(accountId), sub.customer],
);
}
// Mark subscribers as active
await trx.raw("UPDATE subscriber SET status = 'active' WHERE customer_id = ?", [
Expand Down
4 changes: 3 additions & 1 deletion svc/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,9 @@ app.use(async (req, res, next) => {
!unlimitedPaths.includes(req.originalUrl.split("?")[0])
) {
let rateCost = 1;
if (req.method === "POST" && req.route?.path === "/request/:match_id") {
// NOTE: req.route is not set yet in app-level middleware (routing happens later in the /api router),
// so match on the method and path instead
if (req.method === "POST" && /^\/api\/request\/[^/]+\/?$/.test(req.path)) {
rateCost = 10;
}
const command = redis.multi();
Expand Down
Loading