Asincrónico PHP: respaldar de estabilidad de aplicación

asincrónico

PHP asincrónico para respaldar la estabilidad de su aplicación

Asincrónico — Ocurre que algunas partes del sistema o integraciones externas no están disponibles o tienen un tiempo de ejecución prolongado.

Al igual que un panadero no se para y espera a que se hornee el pan, mientras tanto puede preparar otros nuevos, lo mismo ocurre con los usuarios de nuestros sistemas.

  • Podemos permitir que el usuario finalice el registro y envíe correo electrónico de forma asincrónica.
  • Podemos generar el informe de forma asincrónica y enviar el enlace de descarga una vez finalizado.
  • Podemos ejecutar integraciones externas de forma asincrónica, por lo que la indisponibilidad del servicio externo no tiene ningún efecto en el usuario final.

Flujos

Es importante conocer sobre manejo de eventos, analizamos cómo separar los flujos entre sí mediante eventos. Y saber qué flujos tenemos en el sistema, ya que es el flujo el que nos da pistas, si debemos hacerlo asincrónico.

Flujo de registro de usuario

Continuando con el ejemplo de la publicación sobre Manejo de eventos.

Para registrar un usuario, Main Flow estaría creando un usuario y guardándolo en la base de datos.

Los subflujos por otro lado serían:

  • Envío de correo electrónico de bienvenida o confirmación
  • Creación de registros de auditoría sobre el registro de usuarios.
  • Sincronización del usuario registrado con el servicio externo (Integración externa)

Gracias a que definimos claramente qué flujos tenemos en un escenario dado, podemos decidir cuál de ellos puede ejecutarse de forma asincrónica.

Definamos qué problemas podemos resolver eligiendo ejecutar los flujos de forma asincrónica:

1. Llamar al servicio externo puede llevar más tiempo.

El servicio con el que nos integramos puede tener mucho tráfico o algunos problemas de rendimiento.

Al llamar a este código de forma asincrónica, permitimos que el usuario final finalice el registro sin problemas. En segundo lugar, nos permite liberar recursos como la memoria, ya que la solicitud termina de inmediato.

2. El servicio externo puede estar inactivo.

Puede caer porque había mucho tráfico, o un error que hizo que la API fallara o simplemente el proceso de implementación la está poniendo en modo de mantenimiento.

Hacer que el código sea asincrónico nos permite finalizar el registro con éxito, sin importar lo que suceda en el lado de terceros.

3. Podemos terminar en un estado inconsistente.

¿Qué pasa si el correo electrónico se envió con éxito, pero la llamada al servicio externo falló?

Si revertimos la transacción de la base de datos, fallamos el registro, sin embargo, se informará al usuario sobre el registro exitoso.

Si confirmamos la transacción de la base de datos, el servicio externo no tendrá información sobre el usuario.

Ejecutar el código de forma asincrónica nos permite tener éxito en el registro y llamar al servicio externo más tarde, cuando esté en funcionamiento. Entonces siempre terminamos en un estado consistente.


Hacer que el flujo sea asincrónico

Para hacer que un flujo específico sea asíncrono, marcamos Handler como Asynchronous.

 

Puede estar familiarizado con marcar el evento como asincrónico. Este es un enfoque de todo o nada.

Ecotone permite que los manipuladores se marquen como asíncronos. Esto abre la posibilidad para que el desarrollador decida qué controladores específicos deben ejecutarse de forma asincrónica para un evento determinado.

 

La anotación “asincrónico” permite que un controlador específico se ejecute de forma asincrónica utilizando el canal de mensajes “asynchronous_messages”.

 

El canal de mensajes permite abstraer la implementación específica del mecanismo de entrega de mensajes, por lo que su código se limpia de problemas de infraestructura y puede cambiarlo a uno diferente sin tocar el código comercial.

 

Ahora tenemos que elegir el módulo asincrónico.
En este escenario particular, usaremos el módulo RabbitMQ.

Seguimiento del proceso de instalación:

RabbitMQ Support

Y registremos nuestro canal de mensajes para RabbitMQ.

<?php

class Configuration
{
    #[ServiceContext]
    public function enableRabbitMQ()
    {
        return AmqpBackedMessageChannelBuilder::create("asynchronous_messages");
    }
}

 

Puede cambiar fácilmente la implementación del canal de mensajes o hacer uso de diferentes canales para diferentes controladores.

 

Publiquemos el evento de la misma manera que lo hicimos para el código síncrono.

<?php

use Ecotone\Modelling\EventBus;

class PersonRegistrationService
{
    public function __construct(private UserRepository $userRepository, private EventBus $event) {}

    public function registerUser($registerPersonData)
    {
        $person = new Person($registerPersonData);
        $this->userRepository->save($person);
        
        $this->event->publish(new PersonWasRegistered($person->getPersonId()));
    }
}

Ahora puede ejecutar el consumidor para manejar el evento.

El consumidor se registra automáticamente para nosotros y consumirá el mensaje del canal de mensajes “asynchronous_messages”.

Symfony:

bin/console ecotone:run asynchronous_messages -vvv

Laravel:

artisan ecotone:run orders -vvv

Resumen

Hacer el código de forma asincrónica es sencillo en Ecotone.

Esto muestra uno de los principios de Ecotone. Su código quedará limpio de problemas de infraestructura, por lo que puede concentrarse en la funcionalidad comercial y mantener su código limpio.

Recent Post