使用Swoole关闭了学说EntityManager

时间:2019-07-19 01:10:33

标签: doctrine entitymanager swoole

我有一个Laravel应用程序,它正在运行“ swooletw / laravel-swoole”来处理请求。使用laravel-doctrine/orm,将学说用作ORM。

通常,如果某些ORMException被理论抛出了,它会关闭EntityManager,它应该在下一个请求时自动打开/重置。但是当我使用swoole时,这并不会简单发生,除非重新启动swoole worker,否则EntityManager会保持关闭状态。

我试图通过检查entitmanager是否关闭并在中间件中将其重置来解决此问题。因此,在下一个请求时,它应该提供一个新的实体经理。

    protected function handleClosedManagers()
    {
        foreach (Registry::getManagerNames() as $managerName) {
            /** @var EntityManager $manager */
            $manager = Registry::getManager($managerName);
            if (!$manager->isOpen()) {
                Registry::resetManager($managerName);
                $manager = Registry::getManager($managerName);
            }
        }
    }

理想情况下,它应该修复它,但是我得到“ EntityManager已关闭”。

我认为我也需要从laravel容器中刷新它。

所以我将代码更改为此:

 protected function handleClosedManagers()
    {
        foreach (Registry::getManagerNames() as $managerName) {
            /** @var EntityManager $manager */
            $manager = Registry::getManager($managerName);
            if (!$manager->isOpen()) {
                Registry::resetManager($managerName);
                $manager = Registry::getManager($managerName);
                app()->forgetInstance('doctrine.managers.'.$managerName);
                app()->forgetInstance('mem');
                app()->forgetInstance(MagentoEntityManager::class);
                app()->singleton('doctrine.managers.'.$managerName, function () use ($manager) {
                    return $manager;
                });
                // we are using separate entitymanager than default one
                app()->singleton('mem', function () use ($manager) {
                    return $manager;
                });
            }
        }
    }

现在我要坚持下去:

ErrorException: Undefined index: 000000005ba55063000000001b2f101d in file /***/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 3003

有人知道应对这种情况的正确方法吗?

1 个答案:

答案 0 :(得分:0)

我在Zend Expressive应用程序中遇到了同样的问题。

我发现,与其尝试将容器中已关闭的实体管理器和所有可能已注入的服务替换为已关闭的实体管理器,不如通过将其包装到装饰器中来使可重设的实体管理器变得更容易,该装饰器允许将实际的实体管理器替换为需要时的新实例:

final class ResettableEntityManager extends \Doctrine\ORM\Decorator\EntityManagerDecorator
{
    /**
     * @var callable
     */
    private $entityManagerFactory;

    public function __construct(callable $entityManagerFactory)
    {
        $this->entityManagerFactory = $entityManagerFactory;
        parent::__construct($entityManagerFactory());
    }

    public function recreate(): void
    {
        $this->wrapped = ($this->entityManagerFactory)();
    }
}

在每个请求结束时,如果关闭,我会重新创建实体管理器,否则我将其清除以防止内存泄漏:

if ($this->entityManager->isOpen()) {
    $this->entityManager->clear();
} else {
    $this->entityManager->recreate();
}