Workflow transaction
This feature is available in version
2.7.2
or later
Casewhere provides the transaction concept to represent a unit of work, which is made up of multiple operations, performed and treated in a reliable and coherent way. A Casewhere workflow transaction, by definition, must be
- Atomic: It must either be complete in its entirety or have no effect whatsoever
- Consistent: It must conform to existing constraints in Casewhere
- Isolated: It must not affect other transactions
- Durable: It must get written to persistent storage
Transactional activity
Form activity and Scripted activity are transactional activities in Casewhere. Casewhere will reject all changes created during the activity execution if these activities fail to execute for some reason.
Example 1: All changes are rejected if the scripted activity throws an exception
dataApi.Add("Message", new { Status = "Draft", Content = "Message 1" });
dataApi.Add("Message", new { Status = "Draft", Content = "Message 2" });
throw new Exception("Error");
In this example, both Message 1
and Message 2
will not be persisted.
Example 2: Commit transaction
dataApi.Add("Message", new { Status = "Draft", Content = "Message 1" });
ctx.CommitChanges();
dataApi.Add("Message", new { Status = "Draft", Content = "Message 2" });
throw new Exception("Error");
In this example, Message 1
is persisted while Message 2
is not.
Transactional workflow
Casewhere allows to enable transaction for a specific workflow definition. For Automatic Workflow, transaction is enabled by default.
Every time Casewhere persists the workflow state, it will commit all opening transactions and flush all changes to database. These changes once committed will not be rolled back even if the workflow fails to execute the next activities. When you enable transaction for a UI workflow, you will see Casewhere creates a new transaction every time the user click "Save" in the workflow wizard. For automatic workflows where no user interaction is required, Casewhere will run all activities in the same transaction.
When a transaction rolls back, besides the changes in data objects, Casewhere will also discard the following information tracked by the transaction:
- Workflow queue jobs
- Data trigger notifications
- Event trigger events
- Audit logs
In order to understand how transactions work for Casewhere workflows, let's go through the following examples.
Example 1: Error is thrown from a required activity
Assuming we have the following workflow definition:
Workflow 1 (Transaction enabled)
Scripted Activity 1
- The activity saves data successfully
Scripted Activity 2 (Required)
- The activity throws an error
Since the Scripted Activity 2
is required, the Workflow 1
will stop. Since the workflow is transactional, Casewhere will discard all data changes including the ones in Scripted Activity 1
.
Example 2: Error is thrown from an optional activity
Assuming we have the following workflow definition:
Workflow 1 (Transaction enabled)
Scripted Activity 1
- The activity saves data successfully
Scripted Activity 2 (Optional)
- The activity throws an error
Scripted Activity 3
- The activity saves data successfully
Since the Scripted Activity 2
is optional, the Workflow 1
will run to the end. Though the workflow is transactional, Casewhere still persists on changes in Scripted Activity 1
and Scripted Activity 3
, only discard the change if any in Scripted Activity 2
.
Example 3: Error is thrown from nested workflow
Assuming we have the following workflow definition:
Workflow 1 (Transaction disabled)
Scripted Activity 1
- The activity saves data successfully
Workflow Activity 2 (Required, Executed immediately)
Workflow 2 (Transaction enabled)
Scripted Activity 2.1 (Required)
- The activity throws an error
Scripted Activity 3
The Workflow 1
will stop at Workflow Activity 2
because the activity is required. Casewhere will discard all changes in Workflow 2
but still accepts the changes in Scripted Activity 1
because Workflow 1
is not transactional.
Example 4: Error is thrown from a synchronous triggered workflow
Assuming we have the following workflow definition:
Workflow 1 (Transaction enabled)
Scripted Activity 1 (Required)
- Trigger a synchronous workflow
Workflow 2
(through data trigger or event trigger)Workflow 2
executes and throws an error
- Trigger a synchronous workflow
Scripted Activity 2
The Scripted Activity 1
will fail to complete because of the error thrown from Workflow 2
. The Workflow 1
will stop at Scripted Activity 1
because the activity is required. Casewhere will discard all changes in Workflow 1
and Workflow 2
because they share the same transaction context.