队列与 Cron
您要实现的是循环队列。 Cron 仅用于预定事件。
- 构建您的队列管理器/工作者
- 添加一个 cron 条目以调用获取管理器(单例)的命令。
- 作为单例模式的结果,如果它停止了,它将重新开始。
- 除非您将队列的状态存储在该管理器(文件或数据库)之外,否则它可能总是在 cmd4 处死掉,并且永远不会运行后续命令。
前经理
class CommandQueueLoop {
const QUEUE = [
'app:command1' => [
'command' => 'app:command1',
],
'app:command2' => [
'command' => 'app:command2',
'somearg' => 123
],
'app:command3' => [
'command' => 'app:command3',
],
];
private static $queueManager;
private $activeQueue;
private $app;
private $input;
private $output;
private $running;
public function __construct(Application $app, InputInterface $input, OutputInterface $output)
{
$this->app = $app;
$this->input = $input;
$this->output = $output;
$this->running = false;
$this->start();
}
public static function getInstance(Application $app, InputInterface $input, OutputInterface $output)
{
if (!self::$queueManager instanceof self) {
self::$queueManager = new self();
}
}
public function start(array $queue = null)
{
$this->activeQueue = $queue ?? self::QUEUE;
$this->running = true;
$this->run($this->activeQueue);
}
public function stop()
{
$this->running = false;
$this->activeQueue = null;
}
private function run(array $queue)
{
if (!$this->running) {
return;
}
foreach ($queue as $cmd => $args) {
$this->call($cmd, $args);
}
$this->run($this->activeQueue);
}
private function call(string $command, array $args)
{
try {
$cmd = $this->app->find($command);
$inp = new ArrayInput($args);
$returnCode = $cmd->run($inp, $this->output);
} catch (Exception $e) {
// log failure
unset($this->activeQueue[$cmd]); // remove from queue
}
// check returnCode & log
}
}
确保队列正在运行的 Cron 命令
添加这个命令,并且只有这个命令到 cron,每小时一次左右。当它运行时,如果命令已停止,它将重新启动。
class QueueLoopCommand extends Command
{
...
public function execute(InputInterface $input, OutputInterface $output)
{
$queueLoop = CommandQueueLoop::getInstance($this->getApplication(), $input, $output);
}
}
这里是龙
这个“管理器”需要非常仔细地编写,具有良好的日志记录和某种紧急停止功能。此外,该 Cron 命令应该调用“管理器”中的许多其他方法来检查状态、上次运行、仔细检查多个线程等,并对意外状态做一些事情。像这样的构建工具可以快速深入,并且可以像你不会相信的那样把你带入兔子洞。
主要危险: