Implementar la nueva clase WorkQueue, que se encarga de procesar en segundo plano algunas tareas no fundamentales como:
- Actualizar el saldo de la subcuenta cuando modificamos una partida.
- Recalcular el precio de coste del producto cuando modificamos el precio de compra a proveedor.
- Actualizar el precio de compra a proveedor cuando hacemos una compra.
Diseño
Para esto lo mejor es una cola de eventos donde podamos publicar eventos y que los procesos escuchen esos eventos y se ejecuten:
Tendremos por un lado los workers, que son las clases que se encargan de hacer el trabajo necesario cuando llega el evento que esperan. Por ejemplo, habría un worker para recalcular el precio de coste de un producto cuando llega el evento Model.Variante.Update.
Por otro lado tenemos los eventos, como el mencionado Model.Variante.Update, que podemos lanzar añadiendo la correspondiente llamada en el saveUpdate() del modelo Variante. O mejor, lo podemos lanzar desde la clase ModelClass y así tenerlo en todos los modelos, que todos los modelos al hacer saveUpdate() lancen un evento Model.NombreModelo.Update.
Implementación
- La clase debe tener un método send(string $event, string $code, array $valued = []): bool para publicar un evento. Aunque solamente se añadirá realmente si hay workers escuchando ese evento.
- Los eventos se almacenarán en la base de datos, así los eventos que se añadan durante una transacción que se rechaza se eliminarán junto al resto de la transacción.
- Cada vez que se haga un saveInsert() en un modelo se debe publicar el evento Model.NombreModelo.Insert junto al id del modelo. Lo mismo con saveUpdate() y delete().
- La clase debe tener un método addWorker(string $worker, string $event, int $position = 0): void para indicar que cuando se procese el evento se debe ejecutar el worker inidicado.
- Los workers se almacenan en la carpeta Worker del plugin y se registran llamando al método addWorker() desde el Init.php
- Varios workers pueden escuchar un mismo evento. Se procesarán en orden.
- Si el worker devuelve false se detiene el procesamiento del evento, así un worker puede impedir ejecutar el resto.
- El index.php ejecutará cada vez un único evento, justo después de terminar de ejecutar con éxito el controlador.
- El cron ejecutará todos los eventos pendientes.
- La clase debe tener un método para procesar un evento (el que tenga que ser). Debe devolver true si lo ha procesado y false si no había nada que procesar. Así podemos hacer un bucle para llamar a esta función y mientras devuelva true es que hay más que procesar.