具有嵌套闭包,命令和依赖关系的队列管理器

时间:2013-05-29 23:55:28

标签: command queue laravel laravel-4 beanstalkd

我对Laravel很新,我正在尝试创建队列来处理我的处理程序。 处理脚本将由夜间cron作业触发。

我已经设置了beanstalkd并使用队列。 我也有非常简单的命令设置,这将允许我使用artisan启动脚本。我是Laravel的新手,我正在尝试创建队列来处理我的处理程序。 处理脚本将由夜间cron作业触发。

我已经设置了beanstalkd并使用队列。 我也有非常简单的命令设置,这将允许我使用工匠开始一个脚本。

我遇到的主要问题是我的脚本中存在依赖项。 例如:

A -> B -> C
       -> D

我需要脚本A首先成功运行,然后B需要成功运行,然后C和D需要运行但是C和D的顺序并不重要

其中每个都是非常不同的任务,我希望将它们分开,但需要管理队列中的依赖项。我已经创建了模型和库来处理我的处理,一切都很好。

由于我已经在模型中使用了逻辑,因此我只需要对队列进行一次小调用。 最初我想只使用闭包并将其全部写在一个文件中,下面是一个简单的例子。

Queue::push(function($jobA) use ($id)
{
    ProcessA::doStuff($id);
    $jobA->delete();
});

这有效,但这仅适用于A,我仍然需要添加B,C和D. 所以我决定在其中添加一个闭包。

Queue::push(function($jobA) use ($id)
{
    $statusA = ProcessA::doStuff($id);

    if($statusA)
    {
        Queue::push(function($jobB) use ($id)
        {
            ProcessB::doStuff($id);
            $jobB->delete();
        });
    }

    $jobA->delete();
});

这不起作用。 在闭包内部运行闭包似乎存在问题。 在jobB开始之前,jobA可能还有问题被删除。

这个例子比我实际需要做的更简单一些。 这是一个更好的例子......在完成A之后,我现在需要得到一些东西并循环遍历每一个并运行B.然后从早先我说我然后有C和D从B产生。 ..但我还没有进入C和D部分,因为这已经变得复杂了。

Queue::push(function($jobA) use ($id)
{
    $statusA = ProcessA::doStuff($id);

    if($statusA)
    {
        $things = getThings($id);
        foreach($things as $thing)
        {
            Queue::push(function($jobB) use ($thing)
            {
                ProcessB::doStuff($thing);
                $jobB->delete();
            });
        }
    }

    $jobA->delete();
});

所以嵌套的闭包仍然不起作用。 我的下一步是不嵌套闭包,而是编写类。 要开始A过程我必须做

Queue::push('ProcessA', array('id' => $id));

然后

class ProcessA {

    public function fire($job, $data)
    {
        $things = getThings($data['id']);
        foreach($things as $thing)
        {           
            Queue::push('ProcessB', array('thing' => $thing));
        }       

        $job->delete();
    }

}

然后

class ProcessB {

    public function fire($job, $thing)
    {       
        Queue::push('ProcessC', array('id' => $thing['id']));
        Queue::push('ProcessD', array('id' => $thing['id']));
    }       

    $job->delete();

}
此时,只要它们运行,ProcessC和ProcessD就无关紧要了。 这种方法似乎有效,但我认为我有时会遇到问题,因为processA会在ProcessB产生之前完全完成。花了很长时间才弄清楚这些事情,也许这确实很好......需要再测试一下。

此方法还要求我为运行的每个ProcessA / B / C / D创建一个单独的文件,因为Laravel或PHP 5.4中的自动加载魔法。正如你所看到的,每一个都很短。这似乎是一种相当复杂的做事方式。

  • 这种方法在任何方面都有缺陷吗?
  • 我应该以其他方式这样做吗?
  • 我是否应该将初始化为artisan命令并切换到路线并用curl调用它们?
  • 有没有办法让嵌套的闭包工作?

1 个答案:

答案 0 :(得分:1)

我能想出的最简单的方法:只需在第一次关闭完成其工作时触发事件,然后在其他地方听取该事件。当你抓住它时,将下一个作业推入队列等。