CleanupService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. <?php
  2. namespace App\Module\Cleanup\Services;
  3. use App\Module\Cleanup\Logics\TableScannerLogic;
  4. use App\Module\Cleanup\Logics\CleanupPlanLogic;
  5. use App\Module\Cleanup\Logics\CleanupTaskLogic;
  6. use App\Module\Cleanup\Logics\CleanupExecutorLogic;
  7. use App\Module\Cleanup\Logics\BackupLogic;
  8. use App\Module\Cleanup\Models\CleanupPlan;
  9. use App\Module\Cleanup\Models\CleanupTask;
  10. use App\Module\Cleanup\Models\CleanupBackup;
  11. use App\Module\Cleanup\Models\CleanupSqlBackup;
  12. /**
  13. * 清理服务类
  14. *
  15. * 提供对外的清理服务接口
  16. */
  17. class CleanupService
  18. {
  19. /**
  20. * 扫描系统中的所有数据表
  21. *
  22. * @param bool $forceRefresh 是否强制刷新
  23. * @return array 扫描结果
  24. */
  25. public static function scanTables(bool $forceRefresh = false): array
  26. {
  27. return TableScannerLogic::scanAllTables($forceRefresh);
  28. }
  29. /**
  30. * 创建清理计划
  31. *
  32. * @param array $planData 计划数据
  33. * @return array 创建结果
  34. */
  35. public static function createCleanupPlan(array $planData): array
  36. {
  37. return CleanupPlanLogic::createPlan($planData);
  38. }
  39. /**
  40. * 为计划生成内容配置
  41. *
  42. * @param int $planId 计划ID
  43. * @param bool $autoGenerate 是否自动生成
  44. * @return array 生成结果
  45. */
  46. public static function generatePlanContents(int $planId, bool $autoGenerate = true): array
  47. {
  48. return CleanupPlanLogic::generateContents($planId, $autoGenerate);
  49. }
  50. /**
  51. * 基于计划创建清理任务
  52. *
  53. * @param int $planId 计划ID
  54. * @param array $taskOptions 任务选项
  55. * @return array 创建结果
  56. */
  57. public static function createCleanupTask(int $planId, array $taskOptions = []): array
  58. {
  59. return CleanupTaskLogic::createTask($planId, $taskOptions);
  60. }
  61. /**
  62. * 预览计划的清理结果
  63. *
  64. * @param int $planId 计划ID
  65. * @return array 预览结果
  66. */
  67. public static function previewPlanCleanup(int $planId): array
  68. {
  69. return CleanupExecutorLogic::previewPlanCleanup($planId);
  70. }
  71. /**
  72. * 预览任务的清理结果
  73. *
  74. * @param int $taskId 任务ID
  75. * @return array 预览结果
  76. */
  77. public static function previewTaskCleanup(int $taskId): array
  78. {
  79. return CleanupExecutorLogic::previewTaskCleanup($taskId);
  80. }
  81. /**
  82. * 执行清理任务
  83. *
  84. * @param int $taskId 任务ID
  85. * @param bool $dryRun 是否为预演模式
  86. * @return array 执行结果
  87. */
  88. public static function executeCleanupTask(int $taskId, bool $dryRun = false): array
  89. {
  90. return CleanupExecutorLogic::executeTask($taskId, $dryRun);
  91. }
  92. /**
  93. * 为计划创建数据备份
  94. *
  95. * @param int $planId 计划ID
  96. * @param array $backupOptions 备份选项
  97. * @return array 备份结果
  98. */
  99. public static function createPlanBackup(int $planId, array $backupOptions = []): array
  100. {
  101. return BackupLogic::createPlanBackup($planId, $backupOptions);
  102. }
  103. /**
  104. * 为任务创建数据备份
  105. *
  106. * @param int $taskId 任务ID
  107. * @param array $backupOptions 备份选项
  108. * @return array 备份结果
  109. */
  110. public static function createTaskBackup(int $taskId, array $backupOptions = []): array
  111. {
  112. return BackupLogic::createTaskBackup($taskId, $backupOptions);
  113. }
  114. /**
  115. * 恢复数据备份
  116. *
  117. * @param int $backupId 备份ID
  118. * @param array $restoreOptions 恢复选项
  119. * @return array 恢复结果
  120. */
  121. public static function restoreBackup(int $backupId, array $restoreOptions = []): array
  122. {
  123. return BackupLogic::restoreBackup($backupId, $restoreOptions);
  124. }
  125. /**
  126. * 验证备份完整性
  127. *
  128. * @param int $backupId 备份ID
  129. * @return array 验证结果
  130. */
  131. public static function verifyBackup(int $backupId): array
  132. {
  133. return BackupLogic::verifyBackup($backupId);
  134. }
  135. /**
  136. * 获取任务执行进度
  137. *
  138. * @param int $taskId 任务ID
  139. * @return array 进度信息
  140. */
  141. public static function getTaskProgress(int $taskId): array
  142. {
  143. return CleanupTaskLogic::getTaskProgress($taskId);
  144. }
  145. /**
  146. * 停止任务执行
  147. *
  148. * @param int $taskId 任务ID
  149. * @return array 停止结果
  150. */
  151. public static function stopTask(int $taskId): array
  152. {
  153. return CleanupTaskLogic::stopTask($taskId);
  154. }
  155. /**
  156. * 暂停任务执行
  157. *
  158. * @param int $taskId 任务ID
  159. * @return array 暂停结果
  160. */
  161. public static function pauseTask(int $taskId): array
  162. {
  163. return CleanupTaskLogic::pauseTask($taskId);
  164. }
  165. /**
  166. * 恢复任务执行
  167. *
  168. * @param int $taskId 任务ID
  169. * @return array 恢复结果
  170. */
  171. public static function resumeTask(int $taskId): array
  172. {
  173. return CleanupTaskLogic::resumeTask($taskId);
  174. }
  175. /**
  176. * 启动任务执行
  177. *
  178. * @param int $taskId 任务ID
  179. * @return array 启动结果
  180. */
  181. public static function startTask(int $taskId): array
  182. {
  183. return CleanupTaskLogic::startTask($taskId);
  184. }
  185. /**
  186. * 取消任务执行
  187. *
  188. * @param int $taskId 任务ID
  189. * @param string $reason 取消原因
  190. * @return array 取消结果
  191. */
  192. public static function cancelTask(int $taskId, string $reason = ''): array
  193. {
  194. return CleanupTaskLogic::cancelTask($taskId, $reason);
  195. }
  196. /**
  197. * 获取清理统计信息
  198. *
  199. * @param array $filters 筛选条件
  200. * @return array 统计信息
  201. */
  202. public static function getCleanupStats(array $filters = []): array
  203. {
  204. return [
  205. 'plans' => CleanupPlan::getEnabledStats(),
  206. 'tasks' => CleanupTask::getStatusStats(),
  207. 'backups' => CleanupBackup::getStatusStats(),
  208. 'recent_tasks' => CleanupTask::getRecentStats(7),
  209. 'storage' => CleanupBackup::getStorageStats(),
  210. ];
  211. }
  212. /**
  213. * 清理过期备份
  214. *
  215. * @param int $retentionDays 保留天数
  216. * @return array 清理结果
  217. */
  218. public static function cleanExpiredBackups(int $retentionDays = 30): array
  219. {
  220. return BackupLogic::cleanExpiredBackups($retentionDays);
  221. }
  222. /**
  223. * 获取SQL备份列表
  224. *
  225. * @param array $filters 筛选条件
  226. * @return array SQL备份列表
  227. */
  228. public static function getSqlBackups(array $filters = []): array
  229. {
  230. $query = CleanupSqlBackup::with('backup');
  231. // 按备份ID筛选
  232. if (!empty($filters['backup_id'])) {
  233. $query->where('backup_id', $filters['backup_id']);
  234. }
  235. // 按表名筛选
  236. if (!empty($filters['table_name'])) {
  237. $query->where('table_name', 'like', '%' . $filters['table_name'] . '%');
  238. }
  239. // 按记录数量筛选
  240. if (!empty($filters['min_records'])) {
  241. $query->where('records_count', '>=', $filters['min_records']);
  242. }
  243. // 按内容大小筛选
  244. if (!empty($filters['min_size'])) {
  245. $query->where('content_size', '>=', $filters['min_size']);
  246. }
  247. // 排序
  248. $orderBy = $filters['order_by'] ?? 'created_at';
  249. $orderDirection = $filters['order_direction'] ?? 'desc';
  250. $query->orderBy($orderBy, $orderDirection);
  251. // 分页
  252. $perPage = $filters['per_page'] ?? 20;
  253. $result = $query->paginate($perPage);
  254. return [
  255. 'success' => true,
  256. 'data' => $result->items(),
  257. 'pagination' => [
  258. 'current_page' => $result->currentPage(),
  259. 'per_page' => $result->perPage(),
  260. 'total' => $result->total(),
  261. 'last_page' => $result->lastPage(),
  262. ]
  263. ];
  264. }
  265. /**
  266. * 获取SQL备份详情
  267. *
  268. * @param int $sqlBackupId SQL备份ID
  269. * @return array 备份详情
  270. */
  271. public static function getSqlBackupDetail(int $sqlBackupId): array
  272. {
  273. try {
  274. $sqlBackup = CleanupSqlBackup::with('backup')->findOrFail($sqlBackupId);
  275. return [
  276. 'success' => true,
  277. 'data' => [
  278. 'id' => $sqlBackup->id,
  279. 'backup_id' => $sqlBackup->backup_id,
  280. 'backup_name' => $sqlBackup->backup->backup_name ?? '',
  281. 'table_name' => $sqlBackup->table_name,
  282. 'records_count' => $sqlBackup->records_count,
  283. 'content_size' => $sqlBackup->content_size,
  284. 'formatted_size' => $sqlBackup->formatted_size,
  285. 'content_hash' => $sqlBackup->content_hash,
  286. 'sql_preview' => $sqlBackup->sql_preview,
  287. 'backup_conditions' => $sqlBackup->backup_conditions,
  288. 'created_at' => $sqlBackup->created_at,
  289. 'updated_at' => $sqlBackup->updated_at,
  290. ]
  291. ];
  292. } catch (\Exception $e) {
  293. return [
  294. 'success' => false,
  295. 'message' => '获取SQL备份详情失败: ' . $e->getMessage(),
  296. 'data' => null
  297. ];
  298. }
  299. }
  300. /**
  301. * 获取SQL备份内容
  302. *
  303. * @param int $sqlBackupId SQL备份ID
  304. * @return array 备份内容
  305. */
  306. public static function getSqlBackupContent(int $sqlBackupId): array
  307. {
  308. try {
  309. $sqlBackup = CleanupSqlBackup::findOrFail($sqlBackupId);
  310. return [
  311. 'success' => true,
  312. 'data' => [
  313. 'id' => $sqlBackup->id,
  314. 'table_name' => $sqlBackup->table_name,
  315. 'sql_content' => $sqlBackup->sql_content,
  316. 'records_count' => $sqlBackup->records_count,
  317. 'content_size' => $sqlBackup->content_size,
  318. ]
  319. ];
  320. } catch (\Exception $e) {
  321. return [
  322. 'success' => false,
  323. 'message' => '获取SQL备份内容失败: ' . $e->getMessage(),
  324. 'data' => null
  325. ];
  326. }
  327. }
  328. /**
  329. * 清理历史日志
  330. *
  331. * @param int $retentionDays 保留天数
  332. * @return array 清理结果
  333. */
  334. public static function cleanHistoryLogs(int $retentionDays = 30): array
  335. {
  336. return CleanupTaskLogic::cleanHistoryLogs($retentionDays);
  337. }
  338. /**
  339. * 获取系统健康状态
  340. *
  341. * @return array 健康状态
  342. */
  343. public static function getSystemHealth(): array
  344. {
  345. $runningTasks = CleanupTask::running()->count();
  346. $failedTasks = CleanupTask::byStatus(\App\Module\Cleanup\Enums\TASK_STATUS::FAILED->value)
  347. ->where('created_at', '>=', now()->subDay())
  348. ->count();
  349. $expiredBackups = CleanupBackup::expired()->count();
  350. $expiringSoonBackups = CleanupBackup::expiringSoon(3)->count();
  351. $health = 'good';
  352. $issues = [];
  353. if ($runningTasks > 5) {
  354. $health = 'warning';
  355. $issues[] = "有 {$runningTasks} 个任务正在运行,可能存在性能问题";
  356. }
  357. if ($failedTasks > 0) {
  358. $health = 'warning';
  359. $issues[] = "最近24小时内有 {$failedTasks} 个任务执行失败";
  360. }
  361. if ($expiredBackups > 0) {
  362. $health = 'warning';
  363. $issues[] = "有 {$expiredBackups} 个备份已过期,建议清理";
  364. }
  365. if ($expiringSoonBackups > 0) {
  366. $issues[] = "有 {$expiringSoonBackups} 个备份即将过期";
  367. }
  368. if ($failedTasks > 5) {
  369. $health = 'critical';
  370. }
  371. return [
  372. 'health' => $health,
  373. 'issues' => $issues,
  374. 'metrics' => [
  375. 'running_tasks' => $runningTasks,
  376. 'failed_tasks_24h' => $failedTasks,
  377. 'expired_backups' => $expiredBackups,
  378. 'expiring_soon_backups' => $expiringSoonBackups,
  379. ],
  380. ];
  381. }
  382. /**
  383. * 获取推荐的清理计划
  384. *
  385. * @return array 推荐计划
  386. */
  387. public static function getRecommendedPlans(): array
  388. {
  389. $recommendations = [];
  390. // 检查是否有大量日志数据
  391. $logTables = \App\Module\Cleanup\Models\CleanupConfig::byCategory(
  392. \App\Module\Cleanup\Enums\DATA_CATEGORY::LOG_DATA->value
  393. )->get();
  394. if ($logTables->count() > 0) {
  395. $recommendations[] = [
  396. 'type' => 'category',
  397. 'title' => '日志数据清理',
  398. 'description' => '清理系统中的日志数据,释放存储空间',
  399. 'config' => [
  400. 'plan_type' => \App\Module\Cleanup\Enums\PLAN_TYPE::CATEGORY->value,
  401. 'target_selection' => [
  402. 'selection_type' => 'category',
  403. 'categories' => [\App\Module\Cleanup\Enums\DATA_CATEGORY::LOG_DATA->value],
  404. ],
  405. ],
  406. 'estimated_tables' => $logTables->count(),
  407. ];
  408. }
  409. // 检查是否有缓存数据
  410. $cacheTables = \App\Module\Cleanup\Models\CleanupConfig::byCategory(
  411. \App\Module\Cleanup\Enums\DATA_CATEGORY::CACHE_DATA->value
  412. )->get();
  413. if ($cacheTables->count() > 0) {
  414. $recommendations[] = [
  415. 'type' => 'category',
  416. 'title' => '缓存数据清理',
  417. 'description' => '清理系统中的缓存数据,提高系统性能',
  418. 'config' => [
  419. 'plan_type' => \App\Module\Cleanup\Enums\PLAN_TYPE::CATEGORY->value,
  420. 'target_selection' => [
  421. 'selection_type' => 'category',
  422. 'categories' => [\App\Module\Cleanup\Enums\DATA_CATEGORY::CACHE_DATA->value],
  423. ],
  424. ],
  425. 'estimated_tables' => $cacheTables->count(),
  426. ];
  427. }
  428. return $recommendations;
  429. }
  430. }