Appearance
Flow services
Every script gets the flow services: Services in C#, services in Python and JavaScript. The members have the same names in all three languages, so an example in one language reads the same in the others.
| Member | What it gives you |
|---|---|
Log | Write to the flow log |
Messaging | Show messages and progress in the designer |
Settings | Read expression settings |
Storage | Keep values in memory or on disk, and number sequences |
Assets | Read files that come with the flow |
Batches | Group records into a batch |
Alarms | Raise and clear alarms |
Email | Send email through the environment's SMTP server |
Activator | Start another flow |
Flow, Component | Information about the running flow and component |
CancellationToken | Signalled when the flow stops |
HandleExceptionAsync | Report an error and carry on |
Log
Writes to the flow log, which you search in the Logs viewer.
csharp
Services.Log.Information("Order imported");
Services.Log.Warning("Customer has no email", metaData, input);
Services.Log.Error("Payment failed", ex, metaData, input);Levels: Verbose, Debug, Information, Warning, Error, Fatal. Each takes a message and, optionally, the metadata and the record, so the log entry links to the message and its data. Error also takes an exception. The flow's Log level decides which levels are written.
Messaging
Shows messages on the designer, for the people watching the flow.
| Method | What it does |
|---|---|
Information, Warning, Error, Trace | A line in the trace console |
UpdateStatusMessage(text) | Status text on the component |
UpdateProgress(value) | A progress bar on the component, from 0 to 1 |
StopProgress() | Removes the progress bar |
Clear() | Clears the component's messages |
Settings
Reads a value from an expression settings package. Values are cached for 30 seconds, so a changed setting reaches running flows quickly without a restart.
csharp
string url = Services.Settings.Get("Crm", "ApiUrl");
int limit = Services.Settings.Get<int>("Crm", "PageSize"); // C# onlyIn Python and JavaScript, Get returns text; convert it yourself (int(...), Number(...)).
Storage
| Member | Scope | Keeps |
|---|---|---|
Storage.Memory | This flow | Any object, until the flow stops |
Storage.Shared | All flows on the host | Any object, until the host stops |
Storage.Disk | This flow | Bytes, across restarts |
Storage.Sequences | All flows, by name | Number sequences, across restarts |
Memory and Shared have TryGetValue, Add, TryAdd, AddOrUpdate, Get and Delete. Disk has Get, AddOrUpdate and Delete.
csharp
if (!Services.Storage.Memory.TryGetValue<string>("token", out var token))
{
token = await GetTokenAsync();
Services.Storage.Memory.AddOrUpdate("token", token);
}Sequences give unique, increasing numbers that survive restarts:
csharp
Services.Storage.Sequences.NewIfMissing("invoice");
long number = Services.Storage.Sequences.Next("invoice");New(name, start) and Reseed(name, start) set the start value; Delete(name) removes the sequence.
Storage.GetLocalDataPath() returns a folder for the flow's own files, and Storage.GetDatabasePath(name) a path for a local database file.
Assets
Files that come with the flow, such as templates or lookup tables.
csharp
if (Services.Assets.HasAsset("countries.json"))
{
var countries = Services.Assets.GetContent("countries.json").Cast<string>();
}Batches
A batch groups the records produced from one unit of work, such as one file or one query result. Components that work in batches, such as a bulk insert or a file writer, commit when the batch completes and roll back when it fails.
Open a batch, send its records with batch.MetaData, and complete it. Leaving without completing fails the batch.
csharp
await using var batch = Services.Batches.Begin(metaData, input.FileName);
foreach (var line in input.Lines)
await NextAsync(batch.MetaData, new Row { Text = line });
await batch.CompleteAsync();python
with services.Batches.Begin(metaData, inputData.FileName) as batch:
for line in inputData.Lines:
row = Row()
row.Text = line
services.Next(batch.MetaData, row)
batch.Complete()In JavaScript, call batch.Complete() in the try block and batch.Dispose() in finally. batch.Fail() ends a batch as failed on purpose.
Alarms
Raise an alarm defined in the environment's alarm definitions. It is delivered by email, web push or SNMP trap, as the definition says.
csharp
string alarmId = Services.Alarms.Raise("PaymentGatewayDown", "No answer for 60 s", "Payments");
Services.Alarms.Clear("PaymentGatewayDown", alarmId, "Payments");Email
Services.Email.GetDefaultSmtpClient() returns an SMTP client configured for the environment, and GetDefaultSender() the default sender address.
Starting flows
await Services.Activator.Start(flowId) starts another flow by its id.
Flow and component
Services.Flow has the flow's Id, Name, NameSpace and configuration; Services.Component the component's Id and Name.
Errors
HandleExceptionAsync(metaData, inputData, ex) hands a caught exception to the flow's error handling, then your code carries on. Use it in a loop where one bad item shouldn't stop the rest.
csharp
foreach (var item in input.Items)
{
try { await NextAsync(metaData, Map(item)); }
catch (Exception ex) { await Services.HandleExceptionAsync(metaData, input, ex); }
}