DSL 7 - Gestión de timeouts
|
Comenzando
Este paso del tutorial utiliza como punto de partida la solución Si en cualquier momento quieres ver la solución de este paso, la encontrarás en la solución |
Timeouts de acciones
En esta sección veremos cómo gestionamos los timeouts basados en acciones. Supón que tenemos un flujo sencillo que realiza una llamada a un dominio externo: la llamada se efectúa correctamente, pero nunca recibimos la respuesta en el tiempo previsto. En ese escenario, puede que queramos ejecutar alguna acción compensatoria.
Para ilustrarlo, usaremos nuestro sistema de Fraude y veremos cómo afrontamos no recibir respuesta del dominio aguas abajo.
Configurar un timeout de acción (en el DSL)
Configurar timeouts de acción en el DSL es sencillo: solo necesitamos añadir una línea especial de Event Behaviour para indicar al flujo qué enfoque compensatorio adoptar.
Empecemos abriendo MPS y navegando hasta nuestro flujo. Luego añadimos un nuevo Event Behaviour ("Add Event Behaviour").
Añadamos lo básico del comportamiento de evento indicando que aplica sobre el estado "Checking Fraud"; es el estado en el que estaríamos si hubiéramos efectuado correctamente la llamada al sistema de fraude.
Ahora, en "For Event", elegimos un tipo nuevo que aún no habíamos usado: "Action Timeout".
Una vez seleccionado, tenemos que elegir la acción a la que aplica:
Lo primero a notar aquí es el valor por defecto aplicado: "Any action". Esto significa que un timeout de "cualquier acción" en el estado "Checking Fraud" invocará el comportamiento. En nuestro caso, en "Checking Fraud" solo invocamos la acción "Check Fraud", por lo que no marca gran diferencia; pero puede haber ocasiones en las que disparemos múltiples acciones y queramos gestionar el resultado del timeout de cualquiera de ellas.
Para nuestro escenario, simplemente seleccionaremos "Check Fraud".
Ahora debemos indicar "Move To State" y "Perform Actions", como en cualquier otro Event Behaviour. Aquí podríamos hacer lo que haríamos normalmente (llamar a otras acciones, decisiones, etc.). Sin embargo, para simplificar, en este tutorial moveremos nuestro flujo a un estado "Timed Out".
Así que añadamos un nuevo estado llamado "Timed Out" y márcalo como terminal para tratarlo como el final del flujo y que nuestro flujo de iniciación (initiation flow) sepa qué está ocurriendo.
Y lo establecemos como nuestro estado de destino (move to state). No realizaremos acciones adicionales.
Nuestro Event Behaviour se verá así:
Con esto terminamos el trabajo en el DSL. Veamos ahora el gráfico de nuestro flujo.
Abre el flujo desde . Se abrirá el flujo y, a primera vista, no parecerá diferente. Sin embargo, en la parte superior del panel veremos:
Ahora tenemos una nueva opción: "Show Timeouts". Marca esa casilla y pulsa "Apply" para aplicar los cambios (nota: si ya tienes Flo Viewer abierto, puede que tengas que cerrarlo y volver a abrirlo para ver "Show Timeouts").
El nuevo gráfico mostrará:
Aquí vemos que, ante el timeout de "Check Fraud", enrutamos al nuevo estado "Timed Out".
Observa también que el gráfico muestra que esta transición ocurrirá con el evento "CheckFraudActionTimeoutEvent". Este evento es generado por la aplicación cuando la llamada a fraude agota el tiempo.
Implementación en Java
Como siempre, empecemos la implementación regenerando nuestra base de código.
mvn clean install
Veamos un poco cómo funciona el código.
Empezaremos abriendo la interfaz "SchedulerPort" (parte del núcleo de IPF):
public interface SchedulerPort {
void schedule(ScheduleItem var1, Function<ScheduleItem, CompletableFuture<Void>> var2);
void schedule(ScheduleItem var1, Function<ScheduleItem, CompletableFuture<Void>> var2, Duration var3);
void cancel(ScheduleItem var1);
void cancelAll(String var1);
int getRetries(ScheduleItem var1);
}
Son estas funciones las que invocará el código generado siempre que necesite programar (schedule) algo. En nuestro caso, siempre que se llame a una acción, invocará el método schedule y proporcionará un ScheduleItem que contiene los detalles de la acción y un tipo "TIMEOUT".
Así, si indicas al scheduler que deseas un timeout de 10 s para esa acción, devolverá un fallo tras 10 s si la planificación (schedule) sigue activa. Sin embargo, si en ese tiempo se invoca un cancel, esto cerrará el scheduler para ese item.
La aplicación IPF necesita que se proporcione una implementación del puerto de scheduler como parte del dominio. Hasta ahora no hemos tenido que especificar uno. ¿Por qué? Porque por defecto se proporciona un scheduler no-op. Lo que tenemos que hacer ahora es proporcionar una implementación apropiada para nuestro caso.
Akka Scheduler
Podrías usar cualquier scheduler que se ajuste a la interfaz anterior; para este tutorial usaremos otro proporcionado por el framework IPF: AkkaScheduler.
Empecemos añadiendo una dependencia en el pom de ipf-tutorial-app (ipf-tutorial-app/pom.xml):
<dependency>
<groupId>com.iconsolutions.ipf.core.platform</groupId>
<artifactId>ipf-flo-scheduler-akka</artifactId>
</dependency>
A continuación, añadimos el adaptador del scheduler a nuestra configuración de dominio (por ejemplo, en IpfTutorialConfig), pasándolo en el builder cuando construimos el dominio. A partir de ese momento, cuando el framework programe un timeout para una acción, AkkaScheduler lo gestionará y, si expira, se generará el evento de timeout correspondiente (por ejemplo, CheckFraudActionTimeoutEvent) y activará el Event Behaviour que definimos en el DSL para mover el flujo a "Timed Out".
Comprobación de nuestra solución
Inicia la aplicación como antes (si necesitas recordatorio, consulta Revisión de la aplicación inicial).
Envía un pago que provoque que se invoque la acción de fraude y, a continuación, simula (o fuerza) que la respuesta de fraude no llegue. Tras expirar el timeout configurado, deberías ver que el flujo transiciona al estado "Timed Out" y que se ha generado el evento de timeout.