About this Section

In this Section

State and Event Topics offer Publishers and Subscribers a way to provide and consume information. In this section, we discuss the high-level interaction patterns that can be constructed from these building blocks to enable meaningful interaction between different Qeo participants.

Actors and Roles

There are two concepts that are required to describe the interaction:

▪    A Qeo Actor is an individual process or application that participates in Qeo interactions. In a distributed application, one could consider it to be one of the components of the distributed application.

▪    A Role is a well-defined set of responsibilities that can be taken up by an Actor in a distributed application. From the description of the Role, one can deduce the Topics the Actor should subscribe to or publish on. 

Icon

One Actor can play multiple roles simultaneously.

Interaction Patterns

Currently, two main interaction patterns are defined: 

  • Observer Pattern, and the 
  • Directed State Pattern.

The Observer Pattern

Description

This is the basic publish/subscribe interaction pattern.

Roles

The pattern defines two roles:

  • The Subject is either a source of events or an owner of state. The Subject publishes events or state updates on a Qeo Topic.
  • The Observer is interested in a certain type of events or a certain kind of state. It subscribes to a Qeo Topic.

There can be many Subjects and/or many Observers on the same Qeo Topic. Subjects are unaware of the Observers, and (barring explicit modelling in the published data type) Observers are unaware of specific Subjects.

Flow of Information

The flow of information in the pattern is unidirectional: if flows only from Subject to Observer.

Reactive Programming versus Push Style Programming

This pattern fits with the concept of reactive programming, where components do not push other components to perform a certain action, but rather observe their environment and react to changes in that environment. The former approach encourages close coupling of components (the push style requires the pushed component to be present or the system breaks down), whereas the latter approach is more loosely coupled, and hence more robust in a distributed environment.

Directed State Pattern

Description

This is an interaction pattern that allows Actors to drive the global system state forward by expressing their wishes with respect to the state of some other Actor. The key insight of the Directed State Pattern is that one Actor's wishes with respect to the global state can be considered to be part of the Actor's own state. Hence, this "desired state" can be observed, and other Actors can use this information to drive their own state forward.

Roles

The pattern defines two roles:

  • The Effector is an actor that "owns" the state of some physical or logical entities. It publishes this state on the Current State Topic.
  • The Requester is an actor that wants to influence the state owned by the Effector. It publishes its wishes with respect to the Effector's state on the Desired State Topic.

Principle

In essence, the Directed State pattern is the combination of two unidirectional Observer patterns:

  • The Effector is the Subject for the Current State, but acts as Observer for the Desired State
  • The Requester is the Observer of Current State, but the Subject of Desired State

The Effector will observe the Requester's desires, and based on these desires it will decide how to evolve the entities it "owns". This evolution is then reflected in the Current State, which (ideally) evolves towards the Desired State.

Advantages over the Typical RPC Pattern

On the surface, the Directed State Pattern is just a roundabout way for doing an RPC, but there are definitely differences between the two approaches:

  • Instead of one bidirectional exchange, there are two unidirectional communications in this pattern. This means that it is less easy to propagate an error code back when a requested change is not possible. Rather, the Requester must observe the Effector, and conclude that the Current State does not evolve according to its wishes. 
  • There is no hard coupling between the Requester and the Effector: it is quite possible to formulate Desired State in such a way that it is not directed towards any specific Actor, and as such it may be possible that some other Actor A, which can also observe the Desired State, decides to drive its own state forward as a result of the publication done by the Requester. In this way, fault tolerance can be built into the system (other components pick up the work if a given Effector is non-responsive), or new behaviours may be added to the system without breaking old components (A is developed later than our Effector and Requester and implements an additional behaviour the other two don't know about).
  • Because the Requester's wishes are expressed in a data-oriented way (essentially, the Requester is saying "I would like your state to evolve towards this end goal"), the purpose-specific messages of the RPC pattern are avoided. There is one generic way to express any action the Requester wishes the Effector to undertake.