Each process worker runs independently of other workers, and each worker should only access its own data and methods. This independence of workers works well for most solutions.
In some cases, it makes sense to allow workers to work together. As some examples:
- A worker may be logically a part of another worker, and may need to pass data to its parent for the parent to complete.
- One worker may need to know about the state of another worker before continuing.
- It can be useful to make workers visible to additional processes that can then interact with the workers.
These scenarios are achieved through a publish and subscribe mechanism in which a worker publishes a message and subscribers, which may be other workers or groups, then decide how to deal with the message.
Defining a subscription
There are two parts to a subscription: defining what messages to publish to which processes, and then responding to the message within the group or worker than receives the message.
The response to the message is described in a later section.
There are three different types of definition of what should be published.
Group subscriptions are defined on the publication rules field of the group. The publication rules field list groups (or workers) that subscribe to messages published by this group. Each subscription is associated with a reference of the form processType/topic, which defines the combination of processType and topic that should be sent to the group. Either of these can be blank or set to "*" to indicate all process types or all topics. If there is no slash, the reference is assumed to be a process type. Add a suffix of "+" to inherit the subscription down the group hierarchy and for the rule to be applied to groups.
Owner connection subscriptions are defined on publication rules field of the connection group of the owner connection of the worker or group, which typically identifies the source of the worker. These work in the same way as other group subscriptions.
Worker link subscriptions are created automatically by linking workers using the Worker links field, rather than using a separate subscriptions field. The worker links field lists other workers (or groups), and gives each link a link type. Each of these workers will receive messages every time the worker publishes one. Also, workers that link to this worker will receive a message.
Publishing
Data is published from a worker using the Set step type and setting the publish property, either to the name of a topic or to true to indicate that the event type should be used as the topic. The publish can be used at the same time as setting other data, or as a separate step. The publish takes place asynchronously, and other processes may respond to the message after (or before) the worker process execution has completed.
The call to the subscriber always follows the same format. It has an action of @consume, and a data parameter which contains the subscription message in the "message" property.
{
"message": {
"messageIdentifier": "unique-message-identifier",
"reference": "worker.node.reference",
"processIdentifier": "worker-process-identifier",
"role": "role",
"processType": "process_type_reference",
"publicationMode": "publicationMode",
"topic", "topic",
"status": "status",
"data": {.. data ..}
}
}
messageIdentifier | Unique identifier for this message. |
reference | Node reference of the worker. |
processIdentifier | Worker's process identifier. |
role | Worker's role within the process, defaults to "owner". |
processType | The worker's process type reference. |
publicationMode |
The reason the message was published. This can be:
The publication mode may seem the wrong way around to the subscriber. For example, a message from a child will have a publication mode of "parent". Remember that the publication mode is the publisher's view of the reason, not the subscriber's. |
topic |
The topic of the publication. This is taken from one of three sources:
|
status |
The current status of the worker.
|
data |
The data associated with the publish.
|
Responding to messages
The @consume action can do anything. In many cases it will make sense to use the Evaluate step type to interpret the incoming message and route it accordingly. The @consume action should check processType, topic and publicationType to decide what to do. As a suggestion, these values can be meaningfully concatenated as processType.publicationMode.topic, e.g. "raise_order.owner.orderSent" would identify the orderSent topic from the raise_order processes which have as their owner the connection associated with this group, or "project_task.-wbs.finished" to indicate that a project task lower in the work breakdown structure has finished.
The message is passed in to the consumer as the message property of the data parameter, i.e. the message is obtained by:
JSON.parse(application.get('request').getString('data')).message;
A process may receive messages that it cannot process. These should be ignored and no error should be raised.
Subscribers can use the worker reference to call back to the worker, or pass the process identifier and role to a process module which can (assuming it is trusted) then call back to the worker.
Processes do not have to respond to messages sent to them. The @consume action is invoked with a "?" suffix, which means that the call will not fail if the subscriber does not have an @consume action.