This note attempts to summarize the current implementation + usage of statecharts in Alkemio.
The current implementation dates from April 2021, and our understanding of XState + NestJS / JS constructs then was limited, so there may well be good optimizations to be had. What is there now “sort of works” for the limited usage we now have, but it is fragile (has issues) so to step it up further requires revisiting the implementation.
**Near term Business Driver**: Innovation Flow functionality is at the heart of the platform, guiding users on their journey. It is still basically not there, and there is very strong pull from market for it:
* Especially from UWV, who need it very near term
* Also critical for supporting methodologies such as TheoryU, Doughnut Economics, Digicampus Pipeline etc
### Rational for using Statecharts:
* Powerful representation of business logic, bridging development + business
* Allows for shared understanding of progress (“how mature is this challenge? What is the status of my application?”)
### Tooling chosen:
* XState: powerful open source StateChart implementation
* Large + growing community
* Creating strong tooling for working with the
## Reading
* Simple explanation: https://statecharts.dev/what-is-a-statechart.html
* https://xstate.js.org/ – link to XState site itself
* https://stately.ai/ – all new visual editor that has been developed by new venture Stately
* Formal paper re statecharts: https://www.wisdom.weizmann.ac.il/~harel/papers/Statecharts.pdf
## Usage in Alkemio
* Lifecycle entity
* Stores the following:
* Serialized machine definition
* Serialized representation of state of the machine
* Handles events in a generic way
* Exposes various fields for information in the entity
* Note: likely relatively heavy (way too heavy??)
* Event handling: When an event comes in:
* We check that the event is allowed using “standard” privilege logic
* Maybe can go if have guards properly setup in machine definition
* We pass the event to a dedicated service for the target entity (e.g. Challenge) which then has the commands / guards that are applicable for lifecycles in that context”
* “OptionsProvider”: A separate service to
* Isolate the lifecycle guards / commands logic
* Avoid circular reference (was a major issue)
* Options provider then triggers the event to be handled using the Lifecycle service, passing in the following:
* Options provider itself for the commands / guards
* Needed data / entities such as authorization
* Note:
* Guards need to be synchronous
* Commands can be async
* Used in the following places:
* Challenge Innovation Flow
* Opportunity Innovation Flow
* Applications
* Invitations
* Organizational Verification
* Whiteboard checkin / checkout
* Longer term could see way more of the business logic being encapsulated in this framework, simply a much stronger logic representation.
To understand the usage, suggest to look at some of the lifecycle definitions in the server codebase e.g. community/invitation/invitation.lifecycle.config.ts.
## To be done
### Improving current usage:
* Properly handle lifecycle instantiation + triggering transition to “initial state”
* Deal with potential race conditions
* Logic that is executed in commands is on a different thread that then from the incoming graphql mutation handling
* So if carry out a save in the mutation handling then the underlying command action may or may not have completed; has lead to various race conditions e.g. whiteboard checkout / in.
* Approach for managing guards / commands in a generic way
* How does each usage know what guards / commands know are available?
* Should e.g. the InnovationFlow entity have a list of supported guards / commands that can be used + validate for this when instantiating the provided Lifecycle.
* Look at full lifecycle (pun pun) usage of Lifecycles (e.g. how to upgrade etc)
* XState is currently at v4, with a major v5 refresh nearly ready
* Jump now or not?
* V4 likely good for a good while, but will be a huge upgrade challenge.
* Maybe better to jump now to v5 as usage is relatively limited
### Usage for Innovation Flows v2
The functionality needs to expanded to cover I think at least the following:
* Creation of InnovationFlow entity
* Wraps the Lifecycle, which should not in general be directly exposed as the representation of the InnovationFlow
* See Lifecycle as a type (e.g. String)
* Note: also likely needs a visual associated with it, full Profile?
* For each state
* define whether it should be visible
* description
* tbd?
* Logically an Innovation Flow has a number of callouts associated with each State
* Store via name in the state definition?
* Store via InnovationFlow entity?
* Allow extending / managing it within the Challenge e.g. editing callouts for each state?
* When a Challenge is created then it picks up an InnovationFlow template to be used
* Same choice here re picking up associated callouts for usage in the InnovationFlow entity
* Also then need to expand the Innovation Flow Template instance?
* This potentially could be later, and just pick up the machine def for now + then do the association via the Innovation Flow entity for challenges as managed by the Space?
* But UWV would for example want to define the template once + then apply it
### Priorities near term:
* Ensure lifecycle usage is predictable without race conditions
* Extend lifecycle definition with additional information as needed for it being used in UWV / Challenge refresh flows