mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 09:11:12 -05:00
Improve error handling and display for searches and uploads
Enhance user feedback by displaying search errors, refine photo submission fetching, add rate limiting cleanup logic, improve image upload cleanup, and strengthen moderator permission checks. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 2741d09b-80fb-4f0a-bfd6-ababb2ac4bfc Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
@@ -41,36 +41,38 @@ 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, remove entries based on LRU (oldest resetAt)
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
const toDelete = Math.floor(MAX_MAP_SIZE * 0.3); // Remove 30% of entries
|
||||
const sortedEntries = Array.from(rateLimitMap.entries())
|
||||
.sort((a, b) => a[1].resetAt - b[1].resetAt);
|
||||
|
||||
for (let i = 0; i < toDelete && i < sortedEntries.length; i++) {
|
||||
rateLimitMap.delete(sortedEntries[i][0]);
|
||||
}
|
||||
|
||||
console.warn(`Rate limit map reached ${MAX_MAP_SIZE} entries. Cleared ${toDelete} oldest entries.`);
|
||||
}
|
||||
// Handle existing entries (most common case - early return for performance)
|
||||
if (existing && now <= existing.resetAt) {
|
||||
if (existing.count >= MAX_REQUESTS) {
|
||||
const retryAfter = Math.ceil((existing.resetAt - now) / 1000);
|
||||
return { allowed: false, retryAfter };
|
||||
}
|
||||
|
||||
// Create new entry or reset expired entry
|
||||
rateLimitMap.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW });
|
||||
existing.count++;
|
||||
return { allowed: true };
|
||||
}
|
||||
|
||||
if (existing.count >= MAX_REQUESTS) {
|
||||
const retryAfter = Math.ceil((existing.resetAt - now) / 1000);
|
||||
return { allowed: false, retryAfter };
|
||||
// Need to add new entry or reset expired one
|
||||
// Only perform cleanup if we're at capacity AND adding a new IP
|
||||
if (!existing && rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
// First try cleaning expired entries
|
||||
cleanupExpiredEntries();
|
||||
|
||||
// If still at capacity after cleanup, remove oldest entries (LRU eviction)
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
const toDelete = Math.floor(MAX_MAP_SIZE * 0.3); // Remove 30% of entries
|
||||
const sortedEntries = Array.from(rateLimitMap.entries())
|
||||
.sort((a, b) => a[1].resetAt - b[1].resetAt);
|
||||
|
||||
for (let i = 0; i < toDelete && i < sortedEntries.length; i++) {
|
||||
rateLimitMap.delete(sortedEntries[i][0]);
|
||||
}
|
||||
|
||||
console.warn(`Rate limit map reached ${MAX_MAP_SIZE} entries. Cleared ${toDelete} oldest entries.`);
|
||||
}
|
||||
}
|
||||
|
||||
existing.count++;
|
||||
|
||||
// Create new entry or reset expired entry
|
||||
rateLimitMap.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW });
|
||||
return { allowed: true };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user