我使用Queshadilla作业队列插件为CakePhp管理几个重型任务,从excel中提取数据等等。我用一个间隔的cron作业运行shell命令。但是,如果队列中列出了多个作业; shell命令在下一个作业上启动worker而不等待前一个作业的结束或失败。因为我想以非常小的间隔运行shell命令为5秒,并且一些作业需要3分钟才能完全运行;我希望工人等待上一份工作完成,直到那时才开始。
然而,当我用bin/cake CustomQueuesadilla
运行cronjob时;很明显,它开始于一个新的PID等,而不知道前一个是否还在运行。当我将worker的运行时间设置为20秒并将cron作业间隔设置为3分钟时;我每3分钟就有一份工作。但这也意味着如果没有工作,它将等待3分钟 - 20秒再次运行。我想减少这个时间窗口。
我也对架构变化和不同的库开放。
答案 0 :(得分:2)
您尝试实施的是循环队列。 Cron仅适用于预定活动。
(time, command [, error])
。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,每小时一次。当它运行时,如果命令已经停止,它将再次启动。
class QueueLoopCommand extends Command
{
...
public function execute(InputInterface $input, OutputInterface $output)
{
$queueLoop = CommandQueueLoop::getInstance($this->getApplication(), $input, $output);
}
}
这位"经理"需要非常仔细地编写,具有良好的记录和某种紧急停止。另外,Cron Command应该在" manager"中调用其他方法的主机。检查状态,最后一次运行,仔细检查多个线程等,并对意外状态执行某些操作。像这样的建筑工具变得非常快,并且可以像你不相信的那样引导你钻掉兔子洞。
主要危险: