email design

  1. Use of emails
    1. As a message container
    2. Headers
    3. Polling
  2. Overall architecture
    1. Sending and receiving emails
    2. Internal handling of emails
    3. Global context
  3. Waiting on messages
  4. Data containers
    1. Email
    2. Messages

Use of emails

As a message container

Emails are used as a container to send and receive string messages.

The email subject is used for the topic name or service name. The email body contains the string message.


Emails include both standard and non-standard (i.e., custom) headers. Email headers are used to include metadata about each communication instance in a structured way without polluting the content itself (i.e., email body). See Data containers. These custom headers do not have a X- prefix as per RFC 6648.

This metadata is thus also used to be able to differentiate between publisher/subscription messages and service requests/responses. See Overall architecture.

The headers of the service response emails are set so that the email is a reply to the original service request email. This is done by setting the values of the In-Reply-To and References headers of the response email to the value of the Message-ID header of the request email. See page 26 of RFC 5322.

The use of these headers also helps differentiate between a service request and a service response.


To poll for new emails using the IMAP protocol commands, we can:

Overall architecture

Sending and receiving emails

There are three main layers to send and receive messages:

  1. curl: context, executor
  2. email: sender, receiver
  3. publisher/subscription and service client/server

For intraprocess communication, a different set of email sender and email receiver is used:

  1. intraprocess email sender
  2. intraprocess email receiver

Internal handling of emails

Internal handling of emails/mesages is done as follows:

  1. polling manager
  2. handlers: subscription, service client/server
  3. subscriptions, service clients/servers

Global context

A global context owns global objects (i.e., all effectively singletons):

Those objects are made available globally to anything that needs them:

Waiting on messages

Subscriptions and service clients/servers must be waited on through polling. Wait sets can be used to wait for new messages, service requests or service responses. Some utility functions can be used to wait on a specific entity using a wait set without needing to manually create a wait set for that single entity.

Wait sets also support guard conditions as simple conditions with triggers. A guard condition cannot be added to more than one wait set at a time.

Wait sets are empty when created; entities can be added after creation. Wait sets can contain any number of each kind of entity and they can also contain none. Waiting on an empty wait set is valid and is equivalent to a sleep call. Wait sets can be used to wait on the same set of entities multiple times They can also be cleared and re-used to wait on a different set of entities.

Waiting can be:

Data containers


Emails contain:


Basic metadata is provided for all communication instances (i.e., messages, service requests or service responses):

Additionally, for service requests/responses: