98 lines
2.3 KiB
PHP
98 lines
2.3 KiB
PHP
|
|
#!/usr/bin/env php
|
||
|
|
<?php
|
||
|
|
/**
|
||
|
|
* Rate Limit Cleanup Cron Job
|
||
|
|
*
|
||
|
|
* Cleans up expired rate limit files from the temp directory.
|
||
|
|
* Should be run via cron every 5-10 minutes:
|
||
|
|
* */5 * * * * /usr/bin/php /path/to/cron/cleanup_ratelimit.php
|
||
|
|
*
|
||
|
|
* This script can also be run manually for immediate cleanup.
|
||
|
|
*/
|
||
|
|
|
||
|
|
// Prevent web access
|
||
|
|
if (php_sapi_name() !== 'cli') {
|
||
|
|
http_response_code(403);
|
||
|
|
exit('CLI access only');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Configuration
|
||
|
|
$rateLimitDir = sys_get_temp_dir() . '/tinker_tickets_ratelimit';
|
||
|
|
$lockFile = $rateLimitDir . '/.cleanup.lock';
|
||
|
|
$maxAge = 120; // 2 minutes (2x the rate limit window)
|
||
|
|
$maxLockAge = 300; // 5 minutes - release stale locks
|
||
|
|
|
||
|
|
// Check if directory exists
|
||
|
|
if (!is_dir($rateLimitDir)) {
|
||
|
|
echo "Rate limit directory does not exist: {$rateLimitDir}\n";
|
||
|
|
exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Acquire lock to prevent concurrent cleanups
|
||
|
|
if (file_exists($lockFile)) {
|
||
|
|
$lockAge = time() - filemtime($lockFile);
|
||
|
|
if ($lockAge < $maxLockAge) {
|
||
|
|
echo "Cleanup already in progress (lock age: {$lockAge}s)\n";
|
||
|
|
exit(0);
|
||
|
|
}
|
||
|
|
// Stale lock, remove it
|
||
|
|
@unlink($lockFile);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create lock file
|
||
|
|
if (!@touch($lockFile)) {
|
||
|
|
echo "Could not create lock file\n";
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
$now = time();
|
||
|
|
$deleted = 0;
|
||
|
|
$scanned = 0;
|
||
|
|
$errors = 0;
|
||
|
|
|
||
|
|
try {
|
||
|
|
$iterator = new DirectoryIterator($rateLimitDir);
|
||
|
|
|
||
|
|
foreach ($iterator as $file) {
|
||
|
|
if ($file->isDot() || !$file->isFile()) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Skip lock file and non-json files
|
||
|
|
$filename = $file->getFilename();
|
||
|
|
if ($filename === '.cleanup.lock' || !str_ends_with($filename, '.json')) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$scanned++;
|
||
|
|
|
||
|
|
// Check file age
|
||
|
|
$fileAge = $now - $file->getMTime();
|
||
|
|
if ($fileAge > $maxAge) {
|
||
|
|
$filepath = $file->getPathname();
|
||
|
|
if (@unlink($filepath)) {
|
||
|
|
$deleted++;
|
||
|
|
} else {
|
||
|
|
$errors++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch (Exception $e) {
|
||
|
|
echo "Error during cleanup: " . $e->getMessage() . "\n";
|
||
|
|
@unlink($lockFile);
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Release lock
|
||
|
|
@unlink($lockFile);
|
||
|
|
|
||
|
|
// Output results
|
||
|
|
echo "Rate limit cleanup completed:\n";
|
||
|
|
echo " - Scanned: {$scanned} files\n";
|
||
|
|
echo " - Deleted: {$deleted} expired files\n";
|
||
|
|
if ($errors > 0) {
|
||
|
|
echo " - Errors: {$errors} files could not be deleted\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
exit($errors > 0 ? 1 : 0);
|