brucou / kingly

Zero-cost state-machine library for robust, testable and portable user interfaces (most machines compile ~1-2KB)

Home Page:https://brucou.github.io/documentation/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

serialize control state

sytabaresa opened this issue · comments

Hi, i have a question, How a control state_ of a machine can be serialized without breaking Kingly architectural model?
I want to use Kingly in Nodejs server side and I need to load/deserialize the control state and extended state of a user session, make a transition and then unload/serialize that user state/session in a session storage, like Redis.

I know is possible in the case of extended state using the update function and initialExtendedState. but how about control state?

Hi @sytabaresa

Thanks for your question. I do not completely understand it though. Can you elaborate a bit more on your use case server side?

A Kingly state machine is a function produced by a factory from a machine definition. So:

  • if you have all the necessary information, you can create a machine client or server side. That gives you the machine in its initial state.

I assume you want to save a machine in any state, not necessarily the initial state. Is that correct? If that is correct, then in this version of the library it is not possible to do that. It would however be easy for me to add an API that revolves around a pure function such as: (new state, outputs) = fsm(old state, input). If you already have somehow the fsm function server side (or can create it from the machine definition), then you saving the machine would mean saving the state (which is now no longer encapsulated). When you have a new input, you recall the saved state and run fsm with that. This is not hard to do (I actually planned to do sth similar for testing purposes), I can work on that today, but I would like to understand a bit more why this feature is useful to you.

In that new fsm version, the state in question would actually three pieces of state: extended state, history state, and current conrol state. All of this should be serializable if you can stick to JSON for the extended state. The current control state is JSON (string), the history state is JSON too (object) but they are encapsulated inside the machine.

Sebastian, if you pull from the master, you should find a new version which exposes a createPureStateMachine factory with the same parameters as createStateMachine. That factory however returns a function fsm with an interface like mentioned in the previous message:

  • const {outputs, fsmState} = fsm(input) for the machine to process the input with its current state
  • const {outputs, fsmState} = fsm(input, null) for the machine to reset and process the input as its first input (the initial state for the machine is taken from the machine definition)
  • const {outputs, fsmState: newFsmState} = fsm(input2, fsmState) for the machine to process the input after setting its state.

Let me know if that works and I can go ahead making a release and documenting it properly. That should cover all the cases I can think about: you can restart from the beginning (option 2), you can continue (option 1), you can continue from a saved point (option 3). You don't need to know what is in fsmState as you never have to access it, just pass it around.

@sytabaresa I pushed a fix in master that makes sure that the object containing the history state is not mutated. Now that it is no longer internal, not doing so could lead to further calls for fsm writing over the shared history state and a few hard to find bugs down the road. So closed that road. Looking forward to hearing from your feedbck Sebastian so I can add the feature officially.

@sytabaresa no answers so closing this. Feel free to reopen if there is anything new related to this. The feature will remain in the distribution. I haveen't decided yet if and when it will be documented. It should however be replicated by the slim state machine compiler so it is also available for compiled machines.

Nevermind, with the new versions, I see that I can do that with createPureStateMachine, place the deserialized state, make the computation, get the computed state and serialize again in DB. Thanks 😄