Conceptos

Esta sección contiene explicaciones y ayuda para llevar a cabo las siguientes tareas. con eventos de IPF:

  • Suscribiéndose a eventos

  • Uso de implementaciones del evento IPF API

  • Definiendo sus propios eventos para la publicación utilizando el evento API

Event jerarquía

Todos los eventos extienden el nivel superior IPFSystemEvent<T>, que tiene los siguientes miembros: tienen los siguientes miembros (y getters asociados):

public abstract class IPFSystemEvent<T> {
    private static final EventVersion DEFAULT_VERSION = new EventVersion(1, 0, 0);

    private String name;
    private EventLevel level;
    private Instant createdAt;
    private EventVersion version;
    private EventType type;
    private ProcessingContext processingContext;
    private String source;
    private Map<String, String> metadata;
    private T payload;

El IPFSystemEvent está parametrizado, y el T el tipo contiene la carga útil del evento que hereda de este.

Generación y suscripción a eventos

Las dos subsecciones a continuación suponen que se ha creado una implementación de bus. Los eventos API y la implementación se encuentra en dos módulos diferentes para permitir la conectividad de diferentes implementaciones de bus y procesador.

Para utilizar el DefaultEventBus implementación que se utiliza en los ejemplos a continuación, declare las siguientes dependencias en pom.xml:

<dependencies>
    <dependency>
        <groupId>com.iconsolutions.ipf.core.systemevents</groupId>
        <artifactId>ipf-system-events-api</artifactId>
        <version>${ipf-system-events.version}</version>
    </dependency>
    <dependency>
        <groupId>com.iconsolutions.ipf.core.systemevents</groupId>
        <artifactId>ipf-system-events-impl</artifactId>
        <version>${ipf-system-events.version}</version>
    </dependency>
</dependencies>

Los ejemplos a continuación suponen un autobús con el nombre eventBus ya ha sido creado de esta manera:

    private final EventBus eventBus = DefaultEventBus.getInstance();

Suscribiéndose a eventos

Tenga en cuenta que los eventos publicados en un bus antes de que se reconozca una suscripción no se entregarán a ese suscriptor.

Hay dos subscribe métodos como se describe en la interfaz. Aquí está el primero:

    <T extends IPFSystemEvent> boolean subscribe(Class<T> clazz, EventProcessor<? extends T> eventProcessor);

Esta llamada permite el suministro eventProcessor para suscribirse al bus, pero también ofrece una opción adicional Class para denotar un nivel específico en la jerarquía de clases en el que suscribirse. Si consideramos la siguiente jerarquía, por ejemplo:

|- IPFSystemEvent
|--> FunctionalSystemEvent
|---> TestSpecEvent

Podemos emitir un subscribe llame así:

        eventBus.subscribe(TestSpecEvent.class, eventProcessor);

Esto garantizará que este eventProcessor solo reciba eventos de tipo TestSpecEventy sus subclases, y ningún otro tipo de IPFSystem Event.

Utilice esta llamada cuando solo esté interesado en un conjunto específico de eventos.

Aquí está la segunda forma de suscribirse:

    default boolean subscribe(EventProcessor<IPFSystemEvent<?>> eventProcessor) {

Esto es una abreviatura para suscribirse de la siguiente manera:

        var subscribed = eventBus.subscribe(IPFSystemEvent.class, eventProcessor);

Utilice esta llamada si está potencialmente interesado en todos los eventos posibles que pueden ser generados por este sistema.

Ajustando el enfoque con el EventProcessor

Si examinamos la definición de la interfaz de la EventProcessor podemos ver el siguiente método de interfaz (con un valor predeterminado implementación), además de la (esperada)notify:

    /**
     * A predicate to filter which events to accept for processing
     *
     * @return whether this {@link EventProcessor} should process the given {@link IPFSystemEvent}.
     */
    default Predicate<T> predicate() {
        return a -> true;
    }

Este predicado permite al procesador inspeccionar cada mensaje entrante y decidir si está interesado en esto. mensaje particular.

La implementación predeterminada - a → true - permite que todos los eventos pasen. Sobrescribir este método permite un control más detallado control sobre los eventos que se pasan a la notify método.

Vea a continuación diferentes ejemplos de uso de cómo se pueden utilizar los predicados para reducir el enfoque de un procesador.

Generación de eventos

Supongamos que queremos generar un evento que signifique el inicio de un IPF flow. Para hacer eso podemos llamar al raise método como este:

        var testSpecEvent = new TestSpecEvent(PROCESSING_CONTEXT, "B");
        eventBus.raise(testSpecEvent);

Definiendo custom eventos

Para definir custom eventos, cree una clase de evento como una subclase de IPFSystemEvent<T>, donde el T el tipo es el tipo de carga útil que será publicada. Dependiendo del uso del nuevo evento, la carga útil no necesita ser necesariamente serializable, pero se recomienda que se haga así, ya que los eventos generalmente necesitarán ser serializados eventualmente. sobre algún medio (cola de mensajes, archivo, RPC).

Documentación de eventos

Hay una utilidad en el ipf-system-events-api módulo que recupera todas las subclases de IPFSystemEvent en el classpath y puede enumerar sus:

  • Nombre (el getSimpleName() de la clase)

  • Descripción (desde el @EventDescription annotation)

  • Resumen/no resumen

  • Tipo de carga

Semántica de bus

Esta sección define el comportamiento del evento API en situaciones específicas:

Situación Comportamiento

El evento se genera antes de que un suscriptor se suscriba con éxito.

El evento no se entrega al suscriptor.

El suscriptor no recibe la entrega de un evento.

El suscriptor no es notificado nuevamente (entrega como máximo una vez)

Semántica predeterminada del bus de eventos

Todos los eventos tienen una "fuente", definida de manera amplia como el nodo o la aplicación desde la cual se publicó un evento del sistema. El bus de eventos IPF predeterminado busca una Configuración (HOCON) valor llamado ipf.system-events.source, que a su vez es un marcador de posición para ipf.application.name.

Si ipf.system-events.source no se resuelve a un valor en tiempo de ejecución, entonces se utilizará el valor predeterminado, que será la salida de InetAddress.getLocalHost().getHostName(). Si eso genera una excepción, la fuente será UNKNOWN.

En la mayoría de los casos, no necesitará definir ipf.system-events.source, pero usted querrá asegurarse de que su aplicación defina ipf.application.name. Si es necesario que la fuente de eventos del sistema sea diferente del nombre de la aplicación, deberá definir ipf.system-events.source explícitamente.

Tabla 1. Tabla que describe cómo se determina la fuente de eventos del sistema:
Valor de ipf.system-events.source Valor de ipf.application.name Nombre de host actual Fuente

El valor predeterminado:`${? ipf.application.name}`

nombre-de-la-aplicación

nombre-del-anfitrión

nombre-de-la-aplicación

fuente-explícitamente-definida

nombre-de-aplicación

nombre-del-anfitrión

fuente-explícitamente-definida

El predeterminado:`${? ipf.application.name}`

<does not exist>

nombre-del-anfitrión

nombre-del-anfitrión

El predeterminado:`${? ipf.application.name}`

<does not exist>

<unknown or failed to get>

UNKNOWN

Escribiendo un custom implementación del bus de eventos

Si el existente en memoria DefaultEventBus definido en el -impl el paquete es insuficiente, es posible implementar su propio autobús.

Hay un kit de prueba de compatibilidad (TCK) en el -api proyecto que permite a futuros implementadores de autobuses probar la corrección de su implementación.

La prueba está disponible en un test-jar versión de la -api módulo. Cree una dependencia así:

<dependencies>
    <dependency>
        <groupId>com.iconsolutions.ipf.core.systemevents</groupId>
        <artifactId>ipf-system-events-api</artifactId>
        <version>${ipf-system-events.version}</version>
        <type>test-jar</type>
        <scope>test</scope>
    </dependency>
</dependencies>

El TCK es un resumen JUnit clase de prueba - EventBusTestSpec - con el siguiente método abstracto:

    abstract EventBus getEventBus();

Haga que su prueba extienda esta clase e implemente este método abstracto para permitir que la prueba se ejecute. También puede añadir su propio @Test métodos en esta clase (y otras) si desea probar otros escenarios no cubiertos por el TCK.

 Recuerde tener su TCK la clase de implementación termina con la palabra `Test` para que sea recogido automáticamente por el
MavenPlugin Surefire