Skip to content

Design Types and Patterns

Martin Thompson edited this page Sep 2, 2021 · 5 revisions

Throughout Aeron there are a number of common types and approaches that are reused in a number of different scenarios. Generally a naming convention is used to highlight this common behaviour. This page will attempt to outline some of those concepts, describe the common behaviour and point out some example use cases.

Adapter

The purpose of an adapter is to handle incoming messages in their raw binary form and coerce them to application type or types for use elsewhere in the system. A common response to this "oh, this is where serialisation occurs". However, this is not quite correct as in a number of places Aeron doesn't do serialisation, instead it does flyweight based decoding, so much of the serialisation happens lazily. In these cases the Adapter will be doing a partial decode in order to determine the appropriate flyweight to apply to the incoming message.

Some examples of Adapters in Aeron include:

Taking the ConsensusAdapter class for example. Most of its fields that are instances of SBE Decoders. It contains an onFragment callback that matches the FragmentHandler FunctionalInterface, for use in handling messages received via an Aeron Subscription or Image poll call. Within the callback it initially decodes the header of the incoming message, which contains a templateId that identifies the specific decoder to apply to the incoming message. The DriverEventAdapter and ClientCommandAdapter are similar, but contain some small differences. Instead of using SBE decoders, they are using hand written flyweights (the internals of Aeron messaging use these instead of SBE encoders/decoders) and the callback pattern is different as it includes an additional type parameter on the callback. These adapters are being used with the ring buffer that passes messages between the Aeron client and the Media Driver, but the concept is still the same. Both have a switch statement that checks the type of the message and uses that to identify the appropriate flyweight for further processing.

Proxy

Proxies are the inverse of the Adapters. They take a request containing application specific types and coerce them into raw byte arrays for transmission over some media.

Examples include:

The ArchiveProxy and ConsensusModuleProxy are both examples of using SBE to define the encoding flyweights and each has an instances of SBE encoders as fields use to converts the application types into a serialised form, before offering the encoded message onto an Aeron Publication. The DriverProxy in a similar manner to the DriverEventAdapter uses the hand written flyweight do perform the encoding.

Module

The concept of a module is less clearly defined in Aeron. Mostly because the elements that could be considered as modules are not always named as such. A module encapsulates a significant portion of systems functionality. The most obvious example is the ConsensusModule (handles the raft based consensus algorithm for Cluster), however the ClusteredServiceContainer (runs the user defined ClusteredService state machines), Archive (stores streams of data to disk) and even the MediaDriver (manages all remote and IPC communications) itself could be considered modules.

Container

A container is a type of service used to execute some user defined code with a specific interface and lifecycle. The only instance of a container in Aeron is the ClusteredServiceContainer, which exists to run ClusteredService instances. It calls into the appropriate methods on the ClusteredService interface whenever there is a necessary lifecycle event, e.g. start, stop, new leadership term or when a session message arrives.

Agent

A unit in Agrona's agent concurrent model.