Event Server

Event Server is a central component responsible for registering, processing, storing and providing access to events.

Configuration for Event Server is defined with schema hat-event://server.yaml.

Running

By installing Event Server from hat-event package, executable hat-event-server becomes available and can be used for starting this component.

usage: hat-event-server [-h] [--conf PATH]

options:
  -h, --help   show this help message and exit
  --conf PATH  configuration defined by hat-event://server.yaml (default
               $XDG_CONFIG_HOME/hat/event.{yaml|yml|toml|json})

Event Server can be run as standalone component or component connecting to Monitor Server.

Redundancy

To run multiple redundant Event Servers, monitor parameter has to be defined in the configuration. Event Server connects to configured Monitor Server and creates a corresponding Monitor Component. Besides execution of redundancy algorithm, Monitor Server is also used for service discovery. Each Monitor Component is described with its info, that is Component Information. One of the properties of component info is data, through which a component can share some arbitrary information with any other component. Event Server uses data (specified by hat-event://monitor_data.yaml) to share the following information:

  • server_id

    Event Server unique identifier (defined in configuration as server_id). Needed by Eventer Client to request synchronization with the specific server.

  • eventer_server/host and eventer_server/host

    Eventer Server address is needed to any component that uses Eventer Client to interact with currently active Event Server by events.

  • syncer_token (optional property)

    This token string is used as a key for synchronization between Eventer Server and Eventer Client. Event Server will request synchronization with a remote Event Server only if their server_token are identical. If this token is not defined, synchronization is performed irrespective.

Synchronization between Event Servers is based on :ref:` Eventer communication protocol <eventer>`.

If redundant execution is used, each Event Server can operate in two distinct modes:

  • standby

  • operating

Additional transient modes starting and stopping represent transition between starting and operating modes.

Components

Event Server functionality can be defined by using the following components:

Engine

Engine is responsible for creating Modules and executing processing sessions.

This module is available only during operational mode.

Engine’s method register enables registration of events to backend based on a list of register events. Entity who requests registration is identified by Source identifier which is used only during processing of events and is discarded once event is created. There are four types of sources that may register events on Engine:

  • EVENTER Events register by Eventer Server (originating from other components).

  • MODULE Events registered by Modules.

  • ENGINE Events registered by engine itself (e.g. starting and stopping of engine).

  • SERVER Events registered by Event Server internal functions (e.g. synchronization status).

By creating event, Engine enhances register event with:

  • id - unique event identifier,

  • timestamp - single point in time when events are registered. All events registered in a single session get the same timestamp.

Process of creating events based on a single list of register events provided through register is called session. Engine starts new session each time Eventer Server or a module requests new registration through register method. After processing session ends, events are registered with backend. Start and end of each session is notified to each module by calling module’s on_session_start and on_session_stop methods respectively. These methods are called sequentially for each module: only when method of one module ended, method of the other module can be called.

During session processing, each module is notified with a newly created event in case it matches its subscription. By subscription, each module defines event type filter condition used for filtering new events that will get notified to the module. Processing of this event by module can result with new register events. Out of register events, Engine creates events and adds them to the current session. All modules, including the one that added that new events, are notified with new additions. This process continues iteratively until all modules return empty lists of new register events. Processing events by single module is always sequential - Engine keeps order of new events added to session so that new events are always added to the end of the queue for module notification.

Warning

Care should be taken by module implementation not to cause self recursive or mutually recursive endless processing loop.

Engine registers an event that signalizes when the Engine was started or stopped. Event is registered by Engine, with Source.Type set to ENGINE and with event type event/<server_id>/engine where <server_id> represent identification of local server. Source timestamp is set to None and payload is specified by hat-event://events.yaml#/$defs/events/engine.

Eventer Server

Eventer Server module is responsible for providing implementation of server side Eventer communication. This component translates client registration requests to Engine register method calls and client queries to Backend query method calls. At the same time, it observes all new event notifications made by Backend and notifies clients with appropriate messages.

This module is available during standby, starting, operational and stopping modes (event registration is not possible in mode is not operational).

RegisterEvent objects obtained from client’s register requests are forwarded to Engine which converts them to Event and submits to further processing.

A unique identifier is assigned to each chatter connection established with Eventer Server (unique for the single execution lifetime of Event Server process). This identifier is associated with all Event`s obtained from the corresponding connection as through `id of Source (source type is EVENTER).

Each Client makes its subscription to Eventer Server during connection initialization. This subscription is used as a filter for selecting subset of event notifications which are sent to associated connection. In addition to subscription, client can request to be notified only with events with specific server_id.

Eventer Server module is responsible for registering events each time new chatter connection is established and each time existing chatter connection is closed. These events are defined by event type event/<server_id>/eventer/<client_name> where <server_id> represent identification of local server and <client_name> is client identifier obtained during connection initialization. For these events, source timestamp is set to None and payload is specified by hat-event://events.yaml#/$defs/events/eventer.

Eventer Client

If multiple redundant Event Servers are used, each Event Server runs Eventer Client module. This module is used for obtaining and active synchronization of events originating from other Event Server instances.

Eventer Client connets to Eventer server with client name event/<name> where <name> represents configured component’s name.

This module is available during standby, starting, operational and stopping modes.

By continuously monitoring state reported by Monitor Server, Event Server keeps updated list of other available Event Server instances. For each other available instance, new Eventer Client is created. Immediately after connecting to remote Event Server, Eventer Client will query all server events following last event available in local backend. When initial events are retrieved, Eventer Client keeps active connection to remote Event Server and registers new events as they are received. Eventer Client registers received events directly to backend overriding Engines event processing.

During communication with remote Event Server, additional events representing synchronization status will be registered. These events are registered on remote event server via Eventer register message. If local Event Server is in operational mode, these events will also be registered in local Event Server with Engine’s register method together with source SERVER. Event type is event/<server_id>/synced/<remote_server_id> where <server_id> represent identification of local server and <remote_server_id> represent identification of remote server. Source timestamp is set to None and payload is specified by hat-event://events.yaml#/$defs/events/synced.

Immediatly after connection with remote Event Server is established, synced event with state CONNECTED is registered. If first query returns at least one event, synced event with state SYNCING is registered. Once all remote events are queried, synced event with state SYNCED and total number of synced events is registered.

Each time remote Event Server changes state to OPERATIONAL, Eventer Client will register new synced event with last registered synced state. In case of SYNCED state and registration triggered by OPERATIONAL change, new synced event will have count set to null.

Extensions

Core Event Server functionality is used as basis which is extended with Backends and Modules.

Implementation

Documentation is available as part of generated API reference:

Configuration

$schema: "https://json-schema.org/draft/2020-12/schema"
$id: "hat-event://server.yaml"
title: Event Server
description: Event Server's configuration
type: object
required:
    - name
    - server_id
    - backend
    - modules
    - eventer_server
properties:
    type:
        const: event
        description: configuration type identification
    version:
        type: string
        description: component version
    log:
        $ref: "hat-json://logging.yaml"
    name:
        type: string
        description: component name
    server_id:
        type: integer
        description: server identifier
    server_token:
        type:
            - string
            - 'null'
        description: server token
    backend:
        $ref: "hat-event://server.yaml#/$defs/backend"
    modules:
        type: array
        items:
            $ref: "hat-event://server.yaml#/$defs/module"
    eventer_server:
        type: object
        required:
            - host
            - port
        properties:
            host:
                type: string
                default: "127.0.0.1"
            port:
                type: integer
                default: 23012
    adminer_server:
        type: object
        required:
            - host
            - port
        properties:
            host:
                type: string
                default: "127.0.0.1"
            port:
                type: integer
                default: 23015
    monitor_component:
        type: object
        required:
            - host
            - port
            - group
        properties:
            host:
                type: string
                default: "127.0.0.1"
            port:
                type: integer
                default: 23010
            group:
                type: string
$defs:
    backend:
        type: object
        description: |
            structure of backend configuration depends on backend type
        required:
            - module
        properties:
            module:
                type: string
                description: full python module name that implements backend
    module:
        type: object
        description: |
            structure of module configuration depends on module type
        required:
            - module
        properties:
            module:
                type: string
                description: full python module name that implements module