Stem Cell Registry and Message Address Design Notes The heart of Stem is the messaging subsystem and the heart of that is the registry. This is where all knowledge of how to address cells is located. Each cell gets registered by it name and optionally its target and messages are directed to it via its names. The decisions made by the registry when delivering a message are described here as well as the API and other related issues and modules. Stem Message Addresses Stem messages are sent to registered cells by using an address triplet: the hub name, the cell name and the target name. A hub is a single process running Stem. Its name must be unique among all Stem hubs in a single connected net. A hub consists of a set of objects and Stem cells. It contains the message registry, the core Stem system and it will load other modules on demand. A Stem cell is a single object in a Stem hub which has registered itself under a name and can receive messages via its methods. Not all objects in Stem are cells, but all Stem cells are objects. Cells are commonly registered by the Stem::Config system or by a parent cell spawning targeted cells. Only one cell can be registered in a hub for a given cell name. One unusual trick is that a whole class can register itself as a cell by using its class name as the object and some fixed string as the name (sometimes that is the class name as well). There can only be one cell by that class and name but there can be aliases for any cell name. That is used by cells which must be implemented with class level data. The target is the last part of an address and is optional. A given cell could be registered with a cell name and target and it can send and receive messages with its own globally unique address. The cell name is either the parent's cell name or a fixed one for the particular class (the Stem::Log::Filter class does this). The target name is commonly either a Stem::Id value or a name from a configuration. Another use for the target is a cell such as Stem::Switch which uses it to address its input/output maps. The use of the target is defined by the design of the cell. Message Delivery The first step in delivering a message is finding out which cell it goes to. This is done by looking up the cell that matches the hub/name/target address in the message. This is a multistep procedure with the following rules: If the hub name of the message is set and it is not the name of this hub, locate the portal that can send to that hub and deliver the message to that portal. Portal names are in a different namespace as regular cells but portals can also be registered as targeted cells so they can have commands sent to them. See more on Portals below. If the message has a cell name and an optional target name, the cell is looked up in the local registry. Cells with just a cell name don't share the namespace with cells that have cell and target names. If the cell is found the message is delivered by a method. (See how that is chosen below.) If the cell is not found locally it is sent out via a portal with the alias DEFAULT. This portal should be connected to a hub which would know how to direct the message to the proper destination cell. Typically a Stem hub that is a TCP client to a more central server hub will just have its portal to the server aliased to DEFAULT. If the message has the local hub name and couldn't be delivered, it is logged and thrown away. Optionally a delivery failure message could be sent back to the originator. But this is not the Internet and bounces can be automatically fixed in Stem. NOTE: This brings up the whole subject of message routing. I have been thinking about this issue for a while and it is not as tricky as the Internet because of several things. First, we can cheat. Stem is completely in charge of its routing so it can be smart about itself and not deal with worst case situations like the net. A hub can be configured to distribute routing information that supports the network topology. The discovery of the network and its topology can also be automated by a booting Stem network, even from a virgin boot. Remote Stem hubs could be installed with minimal (and not customized) configurations which will cause itself to connect to a server hub and download the real configuration. This simplifies deployment of Stem to a new set of boxes. Much more on this subject will be in another design notes file. Choosing the Cell Method Once the destination cell of a message is determined, you then have to find out its best method to call to deliver that message. Stem's messages can be delivered via a generic method (e.g. 'msg_in') which is expected to take any type of message, or via specific methods (e.g. 'data_in') which handle selected messages. Here are the rules for determining the cell method to call. If the message type is 'cmd' with a command 'foo' and there is a cell method 'foo_cmd', the message is delivered via that method. If a command message is delivered via a command method and a value is returned, that value is sent back to the 'from' address in a response message. For all other message types, if the Cell has a method that is the type name with '_in' appended to it, that method is used for delivery, e.g.; if the message type is 'data', and if the cell has a method named 'data_in', that is called with the message as its sole argument. If the message is not delivered by any of those special methods, it will be delivered to the generic method 'msg_in'. This method should exist in every cell (except those that have the special methods cover all their message types). The method delivery lookup simplifies writing Cells by moving the internal dispatching code from the Cell to the registry. Stem::Id is a simple module designed to manage a set of unique IDs for its owner object, i.e.; it is used by the Stem::SockMsg modules to register all of its accepted/connected sockets with unique targets. Stem::Portal is the class that send messages between hubs over pipes. These pipes can be direct sockets or indirect through a secure transport such as ssh or stunnel. It receives messages vis the 'send' method which are then converted to a string form and written out the pipe. The stringify format is currently Data::Dumper but it can be set via the configuration of the portal to use Storable, XML or something else. Each stringified message is prefixed with 1 or 2 lines containing its size and format. Incoming message strings are converted back into internal messages and then delivered locally by calling dispatch on them. Portals can use any communications channel as long as it gets read and write handles. This means that new security and transport protocols can be integrated easily into the portal.