setName('schedule:message_maintenance') ->setDescription('Schedule and run message maintenance tasks') ->addOption('optimize-indexes', null, Option::VALUE_NONE, 'Run index optimization') ->addOption('clean-messages', null, Option::VALUE_NONE, 'Clean expired messages') ->addOption('days', 'd', Option::VALUE_OPTIONAL, 'Number of days to keep messages (default: 90)', 90) ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, 'Batch size for deletion (default: 1000)', 1000) ->addOption('dry-run', null, Option::VALUE_NONE, 'Perform a dry run without deleting any data'); } protected function execute(Input $input, Output $output) { $optimizeIndexes = $input->getOption('optimize-indexes'); $cleanMessages = $input->getOption('clean-messages'); $days = (int)$input->getOption('days'); $batchSize = (int)$input->getOption('batch-size'); $dryRun = $input->getOption('dry-run'); // 如果没有指定任何选项,则运行所有维护任务 if (!$optimizeIndexes && !$cleanMessages) { $optimizeIndexes = true; $cleanMessages = true; } $output->writeln("Starting scheduled message maintenance tasks..."); $startTime = microtime(true); // 运行索引优化 if ($optimizeIndexes) { $this->runCommand($output, 'optimize:message_indexes'); } // 清理过期消息 if ($cleanMessages) { $options = []; if ($days !== 90) { $options[] = "--days={$days}"; } if ($batchSize !== 1000) { $options[] = "--batch-size={$batchSize}"; } if ($dryRun) { $options[] = "--dry-run"; } $this->runCommand($output, 'clean:expired_messages', $options); $this->runCommand($output, 'clean:expired_group_messages', $options); } $endTime = microtime(true); $executionTime = round($endTime - $startTime, 2); $output->writeln("All maintenance tasks completed in {$executionTime} seconds."); } protected function runCommand(Output $output, $command, array $options = []) { $output->writeln("\nRunning command: {$command}"); $optionsStr = implode(' ', $options); $fullCommand = "php think {$command} {$optionsStr}"; $output->writeln("Executing: {$fullCommand}"); $output->writeln("\nCommand output:"); // 执行命令并实时输出结果 $descriptorSpec = [ 0 => ["pipe", "r"], // stdin 1 => ["pipe", "w"], // stdout 2 => ["pipe", "w"] // stderr ]; $process = proc_open($fullCommand, $descriptorSpec, $pipes); if (is_resource($process)) { // 关闭标准输入 fclose($pipes[0]); // 读取标准输出 while (!feof($pipes[1])) { $line = fgets($pipes[1]); if ($line !== false) { $output->write($line); } } fclose($pipes[1]); // 读取标准错误 $errorOutput = stream_get_contents($pipes[2]); fclose($pipes[2]); // 获取命令执行结果 $exitCode = proc_close($process); if ($exitCode !== 0) { $output->writeln("\nCommand failed with exit code {$exitCode}"); if (!empty($errorOutput)) { $output->writeln("Error output:"); $output->writeln($errorOutput); } } else { $output->writeln("\nCommand completed successfully."); } } else { $output->writeln("Failed to execute command."); } } }