Estoy probando el proyecto asíncrono de spatie. Creé una tarea como tal.
use Spatie\Async\Task; class ServiceTask extends Task { protected $accountService; protected $serviceFactory; public function __construct(ServiceFactory $serviceFactory) { $this->serviceFactory = $serviceFactory; } public function configure() { $this->accountService = $this->serviceFactory->getAccountService(); } public function run() { //accounting tasks } }Y para la piscina:
$pool = Pool::create(); foreach ($transactions as $transaction) { $pool->add(new ServiceTask($serviceFactory)) // handlers ; } $pool->wait();Cuando ejecuto el código anterior, simplemente obtengo
No se permite la serialización de 'Cierre'
Sé que no podemos simplemente serializar un cierre, probé el mismo código anterior con un objeto de transferencia de datos simple y funcionó bien. Pero cuando paso un servicio o una clase de contenedor de Symfony, aparece el error anterior. ¿Hay una solución para esto?
Respuesta corta: no
Respuesta más larga: Spatie Async serializa la tarea antes de agregarla al grupo, por lo que es posible que necesite una solución alternativa.
Vea el código relevante para entender lo que está pasando: Pool::add > ParentRuntime::createProcess > ParentRuntime::encodeTask .
Para obtener más información, consulte este o este problema en la lista de problemas de spatie/async .
Hay muchas alternativas a este problema. Como estás usando Symfony, podrías estar interesado en Symfony Messenger para enviar mensajes a un controlador. Esos controladores pueden usar la inyección de dependencia:
class DefaultController extends AbstractController { public function index(MessageBusInterface $bus) { $bus->dispatch(new ServiceTask('Look! I created a message!')); } } class ServiceTaskHandler implements MessageHandlerInterface { protected $accountService; protected $serviceFactory; public function __construct(ServiceFactory $serviceFactory) { $this->serviceFactory = $serviceFactory; $this->accountService = $this->serviceFactory->getAccountService(); } public function __invoke(ServiceTask $task) { $this->accountService->handle($task); } } Tenga en cuenta que una tarea ( ServiceTask en este ejemplo) también debe ser serializable (como la tarea de spatie/async ). Por lo tanto, puede enviar una identificación como un mensaje y buscar esa identificación en su MessageHandler
La serialización de 'Cierre' no está permitida es un error que se forma al pasar un evento con clave como argumento. Probablemente el problema tenga que ver con crear el objeto en una fábrica y luego pasarlo como parte del constructor.