Skip to content

Instantly share code, notes, and snippets.

@pauci
Created July 3, 2020 14:15
Show Gist options
  • Select an option

  • Save pauci/b34dde239659390646bd01303fa25547 to your computer and use it in GitHub Desktop.

Select an option

Save pauci/b34dde239659390646bd01303fa25547 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
use Doctrine\ORM\EntityManagerInterface;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\VirtualProxyInterface;
use Psr\Container\ContainerInterface;
use Swoole\ArrayObject;
use Swoole\Coroutine;
final class CoroutineEntityManagerDelegator
{
public function __invoke(ContainerInterface $container, string $name, callable $callback): VirtualProxyInterface
{
$factory = new LazyLoadingValueHolderFactory();
return $factory->createProxy(
EntityManagerInterface::class,
static function (?EntityManagerInterface &$wrappedObject) use ($name, $callback): bool {
static $globalContext;
$context = Coroutine::getContext() ?? ($globalContext ??= new ArrayObject());
// Return existing entity manager for current coroutine or create one
$wrappedObject = $context[$name] ??= $callback();
return true;
}
);
}
}
@pauci
Copy link
Author

pauci commented Feb 15, 2022

@Radiergummi does it work for you with enabled coroutines Swoole\Coroutine::enableCoroutine()? I do not know how Symfony DI works, but it seems to me that your entity-manager proxy is using same entity-manager instance that was initially passed to __invoke(), for each coroutine. In my example, the $callback is actual entity-manager factory and is called directly from proxy for every coroutine, so every coroutine gets separate entity-manager instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment