mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 01:45:08 +10:00
653ab3678a
Replace hono-rate-limiter with a Prisma/PostgreSQL bucketed counter approach that works correctly across multiple instances without sticky sessions. - Add RateLimit model with composite PK (key, action, bucket) and atomic upsert - Create rate limit factory with window parsing, bucket computation, and fail-open - Define auth-tier and API-tier rate limit instances - Add Hono middleware, rateLimitResponse helper, and tRPC assertRateLimit helper - Wire rate limit headers through AppError constructor (was declared but never assigned) - Apply rate limits to auth routes (email-password, passkey), tRPC routes (2FA email, link org account), API routes, and file upload endpoints - Add cleanup cron job for expired rate limit rows (batched delete every 15 min) - Remove hono-rate-limiter dependency
37 lines
1.0 KiB
TypeScript
37 lines
1.0 KiB
TypeScript
import { DateTime } from 'luxon';
|
|
|
|
import { prisma } from '@documenso/prisma';
|
|
|
|
import type { JobRunIO } from '../../client/_internal/job';
|
|
import type { TCleanupRateLimitsJobDefinition } from './cleanup-rate-limits';
|
|
|
|
const BATCH_SIZE = 10_000;
|
|
|
|
export const run = async ({ io }: { payload: TCleanupRateLimitsJobDefinition; io: JobRunIO }) => {
|
|
const cutoff = DateTime.now().minus({ hours: 24 }).toJSDate();
|
|
|
|
let totalDeleted = 0;
|
|
let deleted = 0;
|
|
|
|
do {
|
|
// Prisma doesn't support DELETE with LIMIT, so use raw SQL for batching
|
|
// to avoid long-running transactions that could lock the table.
|
|
deleted = await prisma.$executeRaw`
|
|
DELETE FROM "RateLimit"
|
|
WHERE ctid IN (
|
|
SELECT ctid FROM "RateLimit"
|
|
WHERE "createdAt" < ${cutoff}
|
|
LIMIT ${BATCH_SIZE}
|
|
)
|
|
`;
|
|
|
|
totalDeleted += deleted;
|
|
} while (deleted >= BATCH_SIZE);
|
|
|
|
if (totalDeleted > 0) {
|
|
io.logger.info(`Cleaned up ${totalDeleted} expired rate limit entries`);
|
|
} else {
|
|
io.logger.info('No expired rate limit entries to clean up');
|
|
}
|
|
};
|