The workflow state keeps track of the state of the workflow as it progresses. The state is stored in the configured , and can be used to map incoming messages to .
Defining the state
A workflow state is created by extending WorkflowState. The $name property should be unique among all of your workflows.
import { WorkflowState } from '@node-ts/bus-core'
export class FulfilmentWorkflowState extends WorkflowState {
static NAME = 'FulfilmentWorkflowState'
$name = FulfilmentWorkflowState.NAME
// Set of user-defined state properties
itemId: string
customerId: string
status: 'posting-item' | 'sending-receipt' | 'complete'
}
Accessing the state
The state is available as the second parameter to all handlers of a workflow. For example:
import { Workflow } from '@node-ts/bus-core'
export class FulfilmentWorkflow extends Workflow<FulfilmentWorkflowState> {
configureWorkflow (
mapper: WorkflowMapper<FulfilmentWorkflowState, FulfilmentWorkflow>
): void {
mapper
.withState(FulfilmentWorkflowState)
// ...
.when(ItemShipped, 'emailReceipt')
}
// Workflow state is passed in as the second parameter to a workflow handler
async emailReceipt (_: ItemShipped, state: FulfilmentWorkflowState) {
// ...
}
}
Updating the state
The state cannot be modified directly within a handling scope but can be updated by returning the intended changes from a handler. Returning an updated state is optional, and if omitted then no changes to the state will be persisted.
import { Workflow } from '@node-ts/bus-core'
export class FulfilmentWorkflow extends Workflow<FulfilmentWorkflowState> {
configureWorkflow (
mapper: WorkflowMapper<FulfilmentWorkflowState, FulfilmentWorkflow>
): void {
mapper
.withState(FulfilmentWorkflowState)
// ...
.when(ItemShipped, 'emailReceipt')
}
// Workflow state is passed in as the second parameter to a workflow handler
async emailReceipt (_: ItemShipped, state: FulfilmentWorkflowState) {
return { status: 'sending-receipt' }
}
}
Discarding state
There are times when the workflow data shouldn't persist after a message has been handled. This is particularly relevant in cases where a workflow should only handle a message under certain circumstances.
For example, if your workflow is started by an S3ObjectCreated event, but should only create a new workflow if the object key is prefixed with /documents, then this can be achieved by returning this.discardWorkflow() in the workflow like so:
import { Workflow, BusInstance } from '@node-ts/bus-core'
export class ProcessDocumentWorkflow extends Workflow<ProcessDocumentWorkflowState> {
constructor (bus: BusInstance) {}
configureWorkflow (
mapper: WorkflowMapper<ProcessDocumentWorkflowState, ProcessDocumentWorkflow>
): void {
mapper
.withState(ProcessDocumentWorkflowState)
.startedBy(S3ObjectCreated, 'readDocument')
}
async readDocument (event: S3ObjectCreated) {
if (event.s3Key.indexOf('/documents') === 0 {
await this.bus.send(new ReadDocument(event.s3Key))
} else {
// Ignore this message and avoid persisting the workflow state
return this.discardWorkflow()
}
}
}