我有当前的设置:
常规Symfony2 Web请求可以创建并保留Job
实体,该实体也会创建Gearman作业,我们可以在process 1
中进行此操作。 Gearman Job由Gearman Worker执行,该工作人员通过Job
实体的ID
。
我还使用Symfony创建一个Gearman Worker,它作为PHP CLI进程运行,让我们调用process 2
。
对于那些不熟悉Gearman的人来说,工人代码就是这样的:
for loop 5 times
get job from gearman (blocking method call)
get job entity from database
do stuff
本质上,这段代码可以让一个Symfony2实例运行,以便在工作者死亡之前处理5个作业。
我的问题是:在工作人员处理的第一个作业Doctrine2能够使用以下代码从数据库中检索创建的作业而没有问题:
$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById($job->workload()); // workload is the job id
但是,一旦此作业完成并且for循环递增以等待第二个作业,可以说这是来自process 3
上的另一个Symfony2 Web请求,并Job
创建ID
2 ,对Doctrine2存储库的调用返回null,即使该实体肯定在数据库中。
重新启动工作程序可以解决问题,因此当它执行第一个循环时,它可以选择Job
2。
有谁知道为什么会这样? getRepository
或findOneById
的第一次调用是否从MySQL执行某种表缓存,不允许它看到后来添加的Job
2?
只要数据库保持打开状态,MySQL是否只显示数据库到给定连接的快照?
我在尝试第二次调用entityManager
之前尝试重置findOneBy
无效。
感谢您提前获得任何建议,这一点真的让我感到难过。
更新
我创建了一个单独的进程测试用例,以排除它是否是导致问题的并发性,并且测试用例按预期执行。似乎存储库找不到作业2的唯一时间是将其添加到另一个进程的数据库中。
// Job 1 already exists
$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById(1);
$job->getId(); // this is fine.
$em->persist(new Job()); // creates job 2
$em->flush();
$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById(2);
$job->getId(); // this is fine too, no exception.
答案 0 :(得分:1)
也许一个进程在第二个进程保存之前尝试加载实体。
Doctrine通过id来缓存加载的实体,这样当你获得对同一个对象的第二个请求时,它会加载而不会对数据库进行另一个查询。您可以更多地了解Doctrine IdentityMap here