qmuntal/stateless

Allow setting a state machine to some intermediate state

Opened this issue · 2 comments

In scenarios where state machine entities are persisted and outlive a host's memory, and then are later retrieved to act upon, it would be helpful to be able to efficiently load the state machine logic for its current state, to know what it can do and fire off tasks and potentially transition to the next state.

So something like func (sm *StateMachine[S, T]) SetState(state S), to immediately put the StateMachine into the state the entity is in, and act on it from there.

Is there appetite for something like this, and are there any concerns or limitations preventing it from being added?

Hi @husam-e. Thanks for submitting this proposal.

What you are asking is already possible using a state machine with external storage:

var state State = "A"
sm := stateless.NewStateMachineWithExternalStorage(func(_ context.Context) (State, error) {
	return state, nil
}, func(_ context.Context, s State) error {
	state = s
	return nil
}, stateless.FiringQueued)

...

state = "B"

Does it work for you?

Thanks @qmuntal ! I see that can work for one particular entity at a time, where the stateAccessor delegates to a DB fetch or some object that reflects the persisted state. However my thinking is to use the constructed state machine in a more "functional" way, so that I can reuse the same instance as a blueprint for many different entities at any point in time, that can all be in different states.

So thinking of constructing the state machine definition once, holding that in memory, then when handling requests for certain entities in a specific state, identifying what is possible at that state from the state machine defined and then executing those triggers/tasks. And then doing the same for another entity that could be in a different state.

With the current implementation, I think I'd have to reconstruct the state machine for each entity I operate on (so every time I want to do something essentially), and tie the stateAccessor to wherever that particular entity is stored. There may be some performance consequences to that?

(Hope this makes sense!)