Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Workflow Setings

In general, services allow you to specify delivery settings which affect whether the service can run in parallel across one or more sessions, or whether the service can only be run once at a time across all sessions. There are also scope settings which determine whether a given scope is “interruptible”, meaning it cannot be cancelled from the outside—only an internal cancellation or successful termination can end the scope session.

Both of these settings are relevant to a workflow. A workflow is ultimately a service, and therefore supports delivery settings. A workflow has a root scope, and that root scope can have scope settings. Both of these types of settings are bundled into WorkflowSettings.

For blocking, async, and continuous services, you would set delivery instructions via the ServiceBuilder API, which allows you to chain .serial() or .parallel() onto the service name while spawning it. Instead of this chaining approach, workflows allow you to specify their settings by returning one of these from the closure that you use to spawn the workflow:

  • WorkflowSettings: Specify all the workflow settings that you want.
  • DeliverySettings: Specify the delivery settings and use the default scope settings (interruptible).
  • ScopeSettings: Specify the scope settings and use the default delivery settings (parallel).
  • (): Use the default delivery settings (parallel) and scope settings (interruptible). This is what your closure will return if you don’t explicitly return anything.

Here are examples of each:

WorkflowSettings

let workflow = commands.spawn_io_workflow(
    |scope, builder| {
        builder.connect(scope.start, scope.terminate);

        // Return explicit workflow settings.
        WorkflowSettings::new()
            .uninterruptible()
            .with_delivery(DeliverySettings::Serial)
    }
);

DeliverySettings

let workflow = commands.spawn_io_workflow(
    |scope, builder| {
        builder.connect(scope.start, scope.terminate);

        // Return explicit delivery settings.
        // The scope settings will be the default (interruptible).
        DeliverySettings::Serial
    }
);

ScopeSettings

let workflow = commands.spawn_io_workflow(
    |scope, builder| {
        builder.connect(scope.start, scope.terminate);

        // Return explicit scope settings.
        // The delivery settings will be the default (parallel).
        ScopeSettings::uninterruptible()
    }
);

Default

let workflow = commands.spawn_io_workflow(
    |scope, builder| {
        builder.connect(scope.start, scope.terminate);

        // Simply don't return anything from the closure
        // to get the default workflow settings.
    }
);

Nested Scope

When you use the scope operation inside of a workflow, that nested scope can have its own scope settings, independent from the rest of the workflow. This allows you to set specific clusters of operations as uninterruptible.

let workflow = commands.spawn_io_workflow(
    |scope, builder| {
        builder
            .chain(scope.start)
            .then_io_scope(
                |scope, builder| {
                    builder.connect(scope.start, scope.terminate);

                    // Set only this nested scope to be uninterruptible.
                    ScopeSettings::uninterruptible()
                }
            )
            .connect(scope.terminate);
    }
);