ComposeUI

Message Router Requirements

ADR ID
adr-009
Status
Proposed
Scope
global
Deciders
github group
Date
12/6/2021

Context

The Message Router is one of ComposeUI’s core components. It serves as a generic communication layer that modules can build their APIs upon, and as such, needs to be simple, robust and high performing. In this ADR we are listing the requirements for the MVP of the Message Router.

Decision

Simple, topic-based pub-sub

The Message Router should provide a topic-based publisher-subscriber platform with the publish API being as simple as

publish(topic, payload)

where topic is a string and payload is a property bag (or key-value collection).

Language bindings may support serialization/deserialization of strongly typed data from the payload, however the core API will only define the format for the most common, primitive types only. Keys and values should be considered to be strings for the communication layer.

Payload size should be limited to avoid using the Message Router as a content delivery mechanism. For the sake of simplicity, message headers are not supported, mostly to discourage the creation of high level, custom protocols that should be implemented by more suitable technologies.

Service calls

The router should also provide APIs allowing modules to register services that can be invoked by other modules. Service calls should be synchronous (ie. wait for a response). It is the responsibility of language bindings to correlate messages into request-response pairs and provide a simple API for service calls:

response = invoke(service, request)

where service is a string, and request and response are property bags.

The router should handle recursive service calls (A invokes B who invokes A again before returning a response). Such communication patterns should not degrade performance or cause deadlocks.

Plugable message pipelines

There should be an easy-to-configure, plugable pipeline for mapping topics to external services such as Kafka or Azure Service Bus. These plugins will be .NET assemblies loaded into the process of the router, with the ability to inject and intercept messages using a simple API.

High throughput

Since ComposeUI apps are GUI applications, and application components communicate over the Message Router, it should be designed from the ground up for high performance, with cross-process (local) communication in the center.

Delivery guarantees

For cross-process communication, the Message Router should guarantee Exactly Once delivery. However, messages should not be persisted between sessions, that is, pending messages should be deleted when the application shuts down. Messages should also be delivered in strict order at least within a topic or service address, eg. subscribers of a topic should receive messages in the order in which the publisher sent them;

For cross-machine communication, no such guarantees are provided.

Consequences

For the MVP, we must define supported communication protocols early on, as language bindings must also support them. We should use well-known protocols and formats to minimize the cost of implementing language bindings - for this reason, we will likely drop SignalR and similar non-standard mechanism from the list of candidates.