CleanExpiredTokensCommand.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace App\Module\OpenAPI\Commands;
  3. use App\Module\OpenAPI\Models\OpenApiKey;
  4. use App\Module\OpenAPI\Models\OpenApiLog;
  5. use Illuminate\Console\Command;
  6. use Illuminate\Support\Facades\DB;
  7. /**
  8. * 清理过期令牌命令
  9. */
  10. class CleanExpiredTokensCommand extends Command
  11. {
  12. /**
  13. * 命令签名
  14. *
  15. * @var string
  16. */
  17. protected $signature = 'openapi:clean-expired
  18. {--keys : 清理过期的API密钥}
  19. {--logs : 清理过期的调用日志}
  20. {--days=90 : 保留天数}
  21. {--dry-run : 仅显示将要删除的数据,不实际删除}';
  22. /**
  23. * 命令描述
  24. *
  25. * @var string
  26. */
  27. protected $description = '清理过期的API密钥和调用日志';
  28. /**
  29. * 执行命令
  30. *
  31. * @return int
  32. */
  33. public function handle()
  34. {
  35. $cleanKeys = $this->option('keys');
  36. $cleanLogs = $this->option('logs');
  37. $retentionDays = (int)$this->option('days');
  38. $dryRun = $this->option('dry-run');
  39. // 如果没有指定清理类型,默认清理所有
  40. if (!$cleanKeys && !$cleanLogs) {
  41. $cleanKeys = true;
  42. $cleanLogs = true;
  43. }
  44. $this->info('开始清理过期数据...');
  45. $this->line("保留天数: {$retentionDays}");
  46. $this->line("模式: " . ($dryRun ? '预览模式(不实际删除)' : '实际删除'));
  47. $this->line('');
  48. $totalCleaned = 0;
  49. // 清理过期的API密钥
  50. if ($cleanKeys) {
  51. $totalCleaned += $this->cleanExpiredKeys($dryRun);
  52. }
  53. // 清理过期的调用日志
  54. if ($cleanLogs) {
  55. $totalCleaned += $this->cleanOldLogs($retentionDays, $dryRun);
  56. }
  57. $this->line('');
  58. $this->info("清理完成!总共处理了 {$totalCleaned} 条记录。");
  59. return 0;
  60. }
  61. /**
  62. * 清理过期的API密钥
  63. *
  64. * @param bool $dryRun
  65. * @return int
  66. */
  67. protected function cleanExpiredKeys(bool $dryRun): int
  68. {
  69. $this->line('正在检查过期的API密钥...');
  70. // 查找过期的密钥
  71. $expiredKeys = OpenApiKey::where('expires_at', '<', now())
  72. ->where('status', '!=', 'EXPIRED')
  73. ->get();
  74. $count = $expiredKeys->count();
  75. if ($count === 0) {
  76. $this->line('没有找到过期的API密钥。');
  77. return 0;
  78. }
  79. $this->line("找到 {$count} 个过期的API密钥:");
  80. foreach ($expiredKeys as $key) {
  81. $this->line(" - {$key->key_id} ({$key->name}) - 过期时间: {$key->expires_at}");
  82. }
  83. if (!$dryRun) {
  84. // 更新状态为过期,而不是删除
  85. $updated = OpenApiKey::where('expires_at', '<', now())
  86. ->where('status', '!=', 'EXPIRED')
  87. ->update(['status' => 'EXPIRED']);
  88. $this->info("已将 {$updated} 个过期密钥标记为过期状态。");
  89. }
  90. return $count;
  91. }
  92. /**
  93. * 清理过期的调用日志
  94. *
  95. * @param int $retentionDays
  96. * @param bool $dryRun
  97. * @return int
  98. */
  99. protected function cleanOldLogs(int $retentionDays, bool $dryRun): int
  100. {
  101. $this->line("正在检查 {$retentionDays} 天前的调用日志...");
  102. $cutoffDate = now()->subDays($retentionDays);
  103. // 统计要删除的日志数量
  104. $count = OpenApiLog::where('created_at', '<', $cutoffDate)->count();
  105. if ($count === 0) {
  106. $this->line('没有找到需要清理的调用日志。');
  107. return 0;
  108. }
  109. $this->line("找到 {$count} 条需要清理的调用日志({$cutoffDate} 之前)");
  110. if (!$dryRun) {
  111. // 分批删除,避免一次性删除太多数据
  112. $batchSize = 1000;
  113. $totalDeleted = 0;
  114. do {
  115. $deleted = OpenApiLog::where('created_at', '<', $cutoffDate)
  116. ->limit($batchSize)
  117. ->delete();
  118. $totalDeleted += $deleted;
  119. if ($deleted > 0) {
  120. $this->line("已删除 {$deleted} 条日志记录...");
  121. }
  122. } while ($deleted > 0);
  123. $this->info("总共删除了 {$totalDeleted} 条调用日志。");
  124. }
  125. return $count;
  126. }
  127. }