rateLimitService = $rateLimitService; } /** * 执行命令 * * @return int */ public function handle(): int { $logsDays = (int)$this->option('logs'); $rateLimitDays = (int)$this->option('rate-limits'); $statsDays = (int)$this->option('stats'); $dryRun = $this->option('dry-run'); $force = $this->option('force'); $this->info('OpenAPI数据清理工具'); $this->line(''); // 显示清理计划 $this->table(['数据类型', '保留天数', '清理日期之前'], [ ['API调用日志', $logsDays, Carbon::now()->subDays($logsDays)->toDateString()], ['限流记录', $rateLimitDays, Carbon::now()->subDays($rateLimitDays)->toDateString()], ['统计数据', $statsDays, Carbon::now()->subDays($statsDays)->toDateString()], ]); if ($dryRun) { $this->warn('这是一次试运行,不会实际删除数据'); } // 统计将要删除的数据 $logsCount = $this->getExpiredLogsCount($logsDays); $rateLimitsCount = $this->getExpiredRateLimitsCount($rateLimitDays); $statsCount = $this->getExpiredStatsCount($statsDays); $this->line(''); $this->info('将要清理的数据统计:'); $this->table(['数据类型', '记录数'], [ ['API调用日志', number_format($logsCount)], ['限流记录', number_format($rateLimitsCount)], ['统计数据', number_format($statsCount)], ]); if ($logsCount === 0 && $rateLimitsCount === 0 && $statsCount === 0) { $this->info('没有需要清理的数据'); return 0; } // 确认删除 if (!$dryRun && !$force) { if (!$this->confirm('确定要删除这些数据吗?此操作不可恢复!')) { $this->info('操作已取消'); return 0; } } $this->line(''); $this->info('开始清理数据...'); $totalDeleted = 0; // 清理API调用日志 if ($logsCount > 0) { $deleted = $this->cleanLogs($logsDays, $dryRun); $totalDeleted += $deleted; $this->line("✓ 清理API调用日志: " . number_format($deleted) . " 条记录"); } // 清理限流记录 if ($rateLimitsCount > 0) { $deleted = $this->cleanRateLimits($rateLimitDays, $dryRun); $totalDeleted += $deleted; $this->line("✓ 清理限流记录: " . number_format($deleted) . " 条记录"); } // 清理统计数据 if ($statsCount > 0) { $deleted = $this->cleanStats($statsDays, $dryRun); $totalDeleted += $deleted; $this->line("✓ 清理统计数据: " . number_format($deleted) . " 条记录"); } $this->line(''); if ($dryRun) { $this->info("试运行完成,共计将删除 " . number_format($totalDeleted) . " 条记录"); } else { $this->info("数据清理完成,共删除 " . number_format($totalDeleted) . " 条记录"); } return 0; } /** * 获取过期日志数量 * * @param int $days * @return int */ protected function getExpiredLogsCount(int $days): int { $cutoffDate = Carbon::now()->subDays($days); return OpenApiLog::where('created_at', '<', $cutoffDate)->count(); } /** * 获取过期限流记录数量 * * @param int $days * @return int */ protected function getExpiredRateLimitsCount(int $days): int { $cutoffDate = Carbon::now()->subDays($days); return OpenApiRateLimit::where('created_at', '<', $cutoffDate)->count(); } /** * 获取过期统计数据数量 * * @param int $days * @return int */ protected function getExpiredStatsCount(int $days): int { $cutoffDate = Carbon::now()->subDays($days); return OpenApiStats::where('created_at', '<', $cutoffDate)->count(); } /** * 清理API调用日志 * * @param int $days * @param bool $dryRun * @return int */ protected function cleanLogs(int $days, bool $dryRun): int { $cutoffDate = Carbon::now()->subDays($days); if ($dryRun) { return OpenApiLog::where('created_at', '<', $cutoffDate)->count(); } $deleted = 0; $batchSize = 1000; // 分批删除,避免内存溢出 do { $deletedBatch = OpenApiLog::where('created_at', '<', $cutoffDate) ->limit($batchSize) ->delete(); $deleted += $deletedBatch; if ($deletedBatch > 0) { $this->line(" 已删除 {$deleted} 条日志记录..."); } } while ($deletedBatch > 0); return $deleted; } /** * 清理限流记录 * * @param int $days * @param bool $dryRun * @return int */ protected function cleanRateLimits(int $days, bool $dryRun): int { if ($dryRun) { $cutoffDate = Carbon::now()->subDays($days); return OpenApiRateLimit::where('created_at', '<', $cutoffDate)->count(); } // 使用服务类的清理方法 return $this->rateLimitService->cleanExpiredRecords($days); } /** * 清理统计数据 * * @param int $days * @param bool $dryRun * @return int */ protected function cleanStats(int $days, bool $dryRun): int { $cutoffDate = Carbon::now()->subDays($days); if ($dryRun) { return OpenApiStats::where('created_at', '<', $cutoffDate)->count(); } $deleted = 0; $batchSize = 1000; // 分批删除 do { $deletedBatch = OpenApiStats::where('created_at', '<', $cutoffDate) ->limit($batchSize) ->delete(); $deleted += $deletedBatch; if ($deletedBatch > 0) { $this->line(" 已删除 {$deleted} 条统计记录..."); } } while ($deletedBatch > 0); return $deleted; } /** * 清理缓存数据 * * @return void */ protected function cleanCache(): void { $this->info('清理缓存数据...'); // 清理限流缓存 $pattern = 'rate_limit:*'; $keys = \Illuminate\Support\Facades\Cache::getRedis()->keys($pattern); if (!empty($keys)) { \Illuminate\Support\Facades\Cache::getRedis()->del($keys); $this->line("✓ 清理限流缓存: " . count($keys) . " 个键"); } // 清理应用缓存 $pattern = 'openapi_app:*'; $keys = \Illuminate\Support\Facades\Cache::getRedis()->keys($pattern); if (!empty($keys)) { \Illuminate\Support\Facades\Cache::getRedis()->del($keys); $this->line("✓ 清理应用缓存: " . count($keys) . " 个键"); } // 清理权限缓存 $pattern = 'app_scopes:*'; $keys = \Illuminate\Support\Facades\Cache::getRedis()->keys($pattern); if (!empty($keys)) { \Illuminate\Support\Facades\Cache::getRedis()->del($keys); $this->line("✓ 清理权限缓存: " . count($keys) . " 个键"); } } /** * 优化数据库表 * * @return void */ protected function optimizeTables(): void { $this->info('优化数据库表...'); $tables = [ 'kku_openapi_logs', 'kku_openapi_rate_limits', 'kku_openapi_stats', ]; foreach ($tables as $table) { try { \Illuminate\Support\Facades\DB::statement("OPTIMIZE TABLE {$table}"); $this->line("✓ 优化表: {$table}"); } catch (\Exception $e) { $this->warn("优化表 {$table} 失败: " . $e->getMessage()); } } } }