Composition
This guide is about reusability and composition in Sirveo. First, let’s clarify terms:
Reusability is a feature, which prevents or minimizes duplication, and which is necessary for composition.
Composition is a process, in which simpler tasks are composed into more complex ones.
Both are important design goals of Sirveo.
Server Variables
Server variables solves two problems:
- Centralizing configuration parameters for re-use in flows
- Keeping sensitive values and secrets out of flow definitions
In a typical scenario, multiple flows require an authentication token for an API they interact with via HTTP. The token can be configured as a server variable, and marked as a secret. If the server variable is given a key of api_token
, its value can be used in the configuration of HTTP nodes, by using a variable expression:
It will also be accessible in Javascript-capable nodes, task flow conditions and web flow step handler conditions:
This makes it easy to change the behaviour of flows when the secrets they expect are not configured, or contain unexpected behaviour.
The Subflow Node
Re-use is primarily supported by the subflow node, which allows one flow to execute other flows. The subflow node has only two constraints:
(1) Web flows cannot be run by other flows Web flows are designed for input and output to someone operating a browser. System inputs/outputs are supported by webhooks.
(2) A flow cannot execute itself, directly or indirectly The flow engine prohibits shallow and deep loops in subflow execution.
The subflow node can provide input to its target flow. Either from its own node input, or from JSON provided in its configuration, which may use store values via variable expressions.
As a simple example, let’s say that a flow sends a message to a Slack or Telegram channel via HTTP. To make that flow re-usable, it might expect input like this:
And provide output like this:
Now other flows can send messages with this flow, and determine if the message was sent successfully. And without needing to know anything about the internals of the flow that sends the message. In this manner, flows can provide capabilities to other flows, and in a maintainable way.
Let suppose that 10 other flows are using the Slack message flow. Some of those messages may be really important, while requests to the Slack API may fail on occasion. There are a couple of ways to make this notification flow more robust.
It can be modified to retry its request to the API. Or, if the first message request fails, it can use another API as a fall-back, for example, Telegram or some transactional email API.
Alternatively, two other Sirveo features can be leveraged to handle this scenario.
Event Nodes
What happens if the primary and secondary notification mechanisms in the message flow fails? The other flows which rely on the message flow may use it to deliver messages about errors they encounter. In which case it becomes more important to make it robust.
One option is to use an event node. It’s first use is to act as a log, since it can create persistent events with additional data that is stored in the database. If the message flow cannot get the message out via its configured API calls, it can create a message.failed
event, perhaps with some extra detail:
Now the fact that a message delivery failed is at least recorded in the event log, which can be inspected via the UI’s event browser. Note that persistent events may be subject to a retention period, if configured.
That’s great. But it would be really great if that failed message can be automatically retried at a later point in time. Since we have a specific event type to react to (message.failed
), implementing a scheduled retry is easy.
Schedule Nodes
A schedule node creates an instruction for the server scheduler to run another flow, after some (or no) delay, and with optional input data.
To implement delayed retries, we’ll need another flow with a schedule node. A graph flow is ideal, and we can name the flow “reschedule failed message”. It needs one schedule node, configured to:
- run the original message flow
- after a delay of
60m
- With input data configured like this:
Since that is what the message flow expects. Note that this flow is going to receive the message data of the message.failed
event as input data. We’ll configure that next…
Event triggers
Sirveo’s event trigger feature makes it simple to react to, handle or otherwise process specific events with flows.
An event trigger instructs the server, “if you see event type X, run flow Y”. You can configure multiple event triggers for the same event type. The event processor guarantees that your event triggers run sequentially, in a configured order.
For this example, we only need to configure one event trigger:
- For
message.failed
events… - Run our new graph flow, named “reschedule failed message”
Now, notification delivery is much more robust:
- If the message flow’s delivery fails;
- And its secondary mechanism fails,
- It logs a
message.failed
event - The event trigger passes the event’s data to the “reschedule failed message” flow, which;
- creates a once-off schedule trigger
- 1 hour later, the trigger runs the message flow again, with the same input
Additional benefits in this approach:
- Any flow that uses the message flow benefits from the increased reliability, with no modifications
- The message flow itself does not need to “know” what happens to the
message.failed
event it creates. The event trigger feature makes this kind of decoupling very easy to manage - If the server is restarted, existing schedule triggers are resumed, and will run when due
With this setup, the retry will repeat for as long as the message flow fails, or until one of its outbound APIs becomes available again. In which case, it can create a message.sent
event.
Summary
This example demonstrates the essential patterns of re-use and composability in Sirveo, and how specific features support those patterns. In conclusion, here are some useful tips when implementing automations: