mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 07:31:12 -05:00
Improve image handling, optimize hooks, and add rate limiting
This commit introduces several improvements: - Enhances `RideModelCard` by safely accessing and displaying ride count and image data, preventing potential errors. - Refactors `useEntityVersions` and `useSearch` hooks to use `useCallback` and improve performance and prevent race conditions. - Introduces a `MAX_MAP_SIZE` and cleanup mechanism for the rate limiting map in `detect-location` Supabase function to prevent memory leaks. - Adds robust error handling and cleanup for image uploads in `uploadPendingImages`. - Modifies `ManufacturerModels` to correctly map and display ride counts. - Includes error handling for topological sort in `process-selective-approval` Supabase function. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 39bb006b-d046-477f-a1f9-b7821836f3a1 Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
@@ -15,12 +15,39 @@ interface IPLocationResponse {
|
||||
const rateLimitMap = new Map<string, { count: number; resetAt: number }>();
|
||||
const RATE_LIMIT_WINDOW = 60000; // 1 minute in milliseconds
|
||||
const MAX_REQUESTS = 10; // 10 requests per minute per IP
|
||||
const MAX_MAP_SIZE = 10000; // Maximum number of IPs to track
|
||||
|
||||
function cleanupExpiredEntries() {
|
||||
const now = Date.now();
|
||||
for (const [ip, data] of rateLimitMap.entries()) {
|
||||
if (now > data.resetAt) {
|
||||
rateLimitMap.delete(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkRateLimit(ip: string): { allowed: boolean; retryAfter?: number } {
|
||||
const now = Date.now();
|
||||
const existing = rateLimitMap.get(ip);
|
||||
|
||||
if (!existing || now > existing.resetAt) {
|
||||
// If map is too large, clean up expired entries first
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
cleanupExpiredEntries();
|
||||
|
||||
// If still too large after cleanup, clear oldest entries
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
const toDelete = Math.floor(MAX_MAP_SIZE * 0.2); // Remove 20% of entries
|
||||
let deleted = 0;
|
||||
for (const key of rateLimitMap.keys()) {
|
||||
if (deleted >= toDelete) break;
|
||||
rateLimitMap.delete(key);
|
||||
deleted++;
|
||||
}
|
||||
console.warn(`Rate limit map reached size limit. Cleared ${deleted} entries.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Create new entry or reset expired entry
|
||||
rateLimitMap.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW });
|
||||
return { allowed: true };
|
||||
@@ -36,14 +63,7 @@ function checkRateLimit(ip: string): { allowed: boolean; retryAfter?: number } {
|
||||
}
|
||||
|
||||
// Clean up old entries periodically to prevent memory leak
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [ip, data] of rateLimitMap.entries()) {
|
||||
if (now > data.resetAt) {
|
||||
rateLimitMap.delete(ip);
|
||||
}
|
||||
}
|
||||
}, RATE_LIMIT_WINDOW);
|
||||
setInterval(cleanupExpiredEntries, RATE_LIMIT_WINDOW);
|
||||
|
||||
serve(async (req) => {
|
||||
// Handle CORS preflight requests
|
||||
|
||||
Reference in New Issue
Block a user