State machine code with no implementation:
const trainingMachine = createMachine<TrainingContext>({
predictableActionArguments: true,
id: 'training',
initial: 'initial',
context: {},
states: {
initial: {
on: {
REQUESTED: {
target: 'starting',
actions: assign({
trainingRequest: (_context, event) => event.trainingRequest,
user: (_context, event) => event.user,
}),
},
},
},
starting: {
invoke: {
src: 'startTraining',
onDone: {
target: 'waitingForWebhook',
actions: [
assign({
replicateState: (_context, event) => event.data.replicateResponse,
}),
'sendEmailTrainingStarted',
],
},
onError: {
target: 'failure',
actions: assign({
replicateState: (_context, event) => event.data.replicateResponse,
}),
},
},
},
waitingForWebhook: {
on: {
WEBHOOK_ARRIVED: [
{
target: 'processingWebhook',
actions: assign({
replicateState: (_context, event) => event.webhookData,
}),
},
],
},
},
processingWebhook: {
invoke: {
src: 'processWebhook',
onDone: [
{
target: 'waitingForWebhook',
cond: 'webhookStatusInvalid',
},
{
target: 'success',
actions: ['sendEmailTrainingSuccessful'],
},
],
onError: {
target: 'failure',
actions: ['sendEmailTrainingFailed'],
},
},
},
success: {
type: 'final',
},
failure: {
type: 'final',
},
},
})
All services I call via src
are functions returning promises. There are no sub-machines in this case.
How I create and operate the machine:
- Create a 'complete' machine with
trainingMachine.withConfig(implementation)
- Look if I have a saved state for this machine in the DB. If so, get and JSON.parse() it
- Create a service via
interpret(machine)
- Add an onTransition callback that would rewrite the saved state in the DB if
newState.changed
is true - Call
service.start(existingState ? State.create(existingState) : undefined)
- Check that the current status is what I expect it to be, otherwise throw
- Feed it the event, e.g.
trainingService.send('WEBHOOK_ARRIVED', { webhookData })
await waitFor(trainingService, (state) => ...)
specifying the status(es) I expect to arrive atservice.stop()
(I don't know if it's important to call it)- Exist the process, e.g. return the HTTP response.