94 lines
3.2 KiB
PHP
94 lines
3.2 KiB
PHP
|
|
<?php
|
||
|
|
// application/common/command/EmergencyGiftQueue.php
|
||
|
|
|
||
|
|
namespace app\common\command;
|
||
|
|
|
||
|
|
use think\console\Command;
|
||
|
|
use think\console\Input;
|
||
|
|
use think\console\Output;
|
||
|
|
use think\console\input\Option;
|
||
|
|
use think\Log;
|
||
|
|
use app\common\library\GiftQueue;
|
||
|
|
|
||
|
|
class EmergencyGiftQueue extends Command
|
||
|
|
{
|
||
|
|
protected function configure()
|
||
|
|
{
|
||
|
|
$this->setName('emergency:gift_queue')
|
||
|
|
->setDescription('紧急处理积压送礼队列')
|
||
|
|
->addOption('limit', 'l', Option::VALUE_OPTIONAL, '最大处理数量', 10000)
|
||
|
|
->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, '每批处理数量', 500)
|
||
|
|
->addOption('concurrent', 'c', Option::VALUE_OPTIONAL, '并发进程数', 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function execute(Input $input, Output $output)
|
||
|
|
{
|
||
|
|
$limit = $input->getOption('limit');
|
||
|
|
$batchSize = $input->getOption('batch-size');
|
||
|
|
$concurrent = $input->getOption('concurrent');
|
||
|
|
|
||
|
|
$output->writeln("<info>开始紧急处理积压送礼队列...</info>");
|
||
|
|
$output->writeln("最大处理: {$limit}, 批量大小: {$batchSize}, 并发数: {$concurrent}");
|
||
|
|
|
||
|
|
if ($concurrent > 1) {
|
||
|
|
// 多进程处理
|
||
|
|
$this->multiProcess($output, $limit, $batchSize, $concurrent);
|
||
|
|
} else {
|
||
|
|
// 单进程处理
|
||
|
|
$result = GiftQueue::emergencyProcess($limit, $batchSize);
|
||
|
|
$this->outputResult($output, $result);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function multiProcess($output, $limit, $batchSize, $concurrent)
|
||
|
|
{
|
||
|
|
$perProcess = ceil($limit / $concurrent);
|
||
|
|
|
||
|
|
$output->writeln("每个进程处理: {$perProcess}条");
|
||
|
|
|
||
|
|
$pids = [];
|
||
|
|
|
||
|
|
for ($i = 0; $i < $concurrent; $i++) {
|
||
|
|
$pid = pcntl_fork();
|
||
|
|
|
||
|
|
if ($pid == -1) {
|
||
|
|
$output->writeln("<error>创建子进程失败</error>");
|
||
|
|
exit(1);
|
||
|
|
} elseif ($pid == 0) {
|
||
|
|
// 子进程
|
||
|
|
$result = GiftQueue::emergencyProcess($perProcess, $batchSize);
|
||
|
|
$output->writeln("子进程 {$i} 完成: " . json_encode($result));
|
||
|
|
exit(0);
|
||
|
|
} else {
|
||
|
|
// 父进程
|
||
|
|
$pids[] = $pid;
|
||
|
|
$output->writeln("启动子进程 {$i}, PID: {$pid}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 等待所有子进程完成
|
||
|
|
foreach ($pids as $pid) {
|
||
|
|
pcntl_waitpid($pid, $status);
|
||
|
|
$output->writeln("子进程 {$pid} 已完成");
|
||
|
|
}
|
||
|
|
|
||
|
|
// 输出最终统计
|
||
|
|
$finalSize = GiftQueue::size();
|
||
|
|
$output->writeln("<info>所有进程处理完成,剩余队列大小: {$finalSize}</info>");
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function outputResult($output, $result)
|
||
|
|
{
|
||
|
|
$output->writeln("处理结果:");
|
||
|
|
$output->writeln("总计处理: {$result['total_processed']}");
|
||
|
|
$output->writeln("成功: {$result['total_success']}");
|
||
|
|
$output->writeln("失败: {$result['total_failed']}");
|
||
|
|
$output->writeln("剩余队列大小: {$result['remaining']}");
|
||
|
|
|
||
|
|
if ($result['remaining'] > 0) {
|
||
|
|
$output->writeln("<comment>队列仍有积压,建议增加并发处理</comment>");
|
||
|
|
} else {
|
||
|
|
$output->writeln("<info>队列积压已清理完成</info>");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|