Design

Approach

The preferred approach is to leverage a Message Bus and possibly a Messaging Framework that uses the message bus for transport. The advantages over home grown and/or point-to-point solutions are as follows:

  • Hub and Spoke topology. Each node knows the address of the broken but not each other.
  • Key-based routing. Nodes are associated with properties instead of IP addresses.
  • Reliable message delivery.
  • Message queueing.
  • Automatic reconnect behaviour.
  • And probably others …
_images/topology.png

Dispatch Architecture:

_images/dispatch.png

Messaging

A Messaging Framework provides RMI (Remote Method Invocation) & Event semantics on top of messaging. This gives application developers an easy to use abstraction and hides some of the complexities of exchange and dispatching. Especially in OO applications, invoking a method remotely on an agent without regard for message exchange and routing enhances reliability and productivity.

Requirements Summary:

  • Key-based routing based on consumer ID.
  • Synchronous RMI.
  • Asynchronous RMI.
  • Fire and Forget
  • Callbacks
  • Returned values.
  • Exception propagation.
  • Easy to use.
  • Easy to extend classes/method exposed for RMI.
  • Events
  • Support multiple API versions.

Synchronous RMI:

_images/sync.png

Asynchronous RMI:

_images/async.png

Messages

The message format is json:

  • Security-Wrapper:
    • signature - A base64 encoded signature.
    • message - A json message with stricture of: (Request | Result | Exception)
  • Envelope:
    • sn - Serial Number (uuid).
    • version - The API version.
    • routing - A tuple containing the amqp (sender, destination).
    • secret - The (optional) shared secret used for request authentication. DEPRECATED in 2.7.
    • pam - The (optional) PAM authentication credentials. DEPRECATED in 2.7.
    • replyto - The reply amqp address (optional).
    • one of
      • request - An RMI request. See: Request.
      • result - An RMI result. Has value of: (Result | Exception).
      • status - An RMI request status report. See: Status.
    • timestamp - An ISO-8601 reply timestamp (UTC).
    • data - User defined data.
  • Request(Envelope):
    • classname - The target class name.
    • cntr - The (optional) remote class constructor arguments. format: ([],{}).
    • method - The target instance method name.
    • args[] - The list of parameters passed to method
    • kws{} - The named keyword arguments passed to method.
  • Status(Envelope):
    • status - A request status with value of
      • accepted - Accepted by the agent and queued.
      • rejected - Rejected by the agent.
      • started - The request has started execution.
      • progress - Progress is begin reported. See: Progress.
  • Progress(Status):
    • total - The total number of items to be completed.
    • completed - The number of items completed.
    • details - Reported details. Can be anything.
  • Result(Envelope):
    • retval - The returned data. Can be anything.
  • Exception(Envelope)
    • exval - The formatted exception (including trace).
    • xmodule - The exception module name.
    • xclass - The exception class.
    • xstate - The exception state. Contains the exception __dict__.
    • xargs - The exception args attribute when subclass of Exception.

Example RMI request message:

{
   "sn": "e7e91fb6-611b-4284-a9ed-ac1636b2c709",
   "routing": [
       "cfa806a4-919a-495f-b1dd-3fc11be9a8d0" ,
       "19802a28-a18c-4ae3-ac57-b7a2e78a427a"
   ],
   "replyto": "cfa806a4-919a-495f-b1dd-3fc11be9a8d0",
   "version": "0.2"
   "request": {
       "classname": "Dog",
       "method": "bark"
       "args": ["hello"],
       "kws": {}
   }
}

Example reply:

{
   "sn": "e7e91fb6-611b-4284-a9ed-ac1636b2c709",
   "version": "0.2",
   "result": {
       "retval": "Yes master.  I will bark because that is what dogs do."
   }
}

Example status reply:

{
   "origin": "123",
   "status": "accepted",
   "version": "0.2",
   "sn": "985cb165-d291-47de-ab34-ecb20895384e",
   "data": "group 2"
}