diff --git a/docs/src/reference/asciidoc/appendix.adoc b/docs/src/reference/asciidoc/appendix.adoc index a6ab569a..55b34403 100644 --- a/docs/src/reference/asciidoc/appendix.adoc +++ b/docs/src/reference/asciidoc/appendix.adoc @@ -315,3 +315,43 @@ using a Zookeeper with a Spring State Machine. This article is not complete as it requires jepsen tests which are planned for next release. ==== + +As mentioned in <> distibuted states are enabled by +wrapper an instance of a `StateMachine` within a +`DistributedStateMachine`. Specific `StateMachineEnsemble` +implementation is `ZookeeperStateMachineEnsemble` providing +integration with a zookeeper. + +=== ZookeeperStateMachinePersist +We wanted to have a generic interface `StateMachinePersist` which is +able to persist `StateMachineContext` into an arbitrary storage and +`ZookeeperStateMachinePersist` is implementing this interface for a +zookeeper. + +=== ZookeeperStateMachineEnsemble +While distributed state machine is using one set of serialized context +to update its own state, with zookeeper we're having a conceptual +problem how these context changes can be listened. We're able to +serialize context into a zookeeper znode and eventually listen when +znode data is modified. However zookeeper doesn't guarantee that you +will get notification for every data change because registered watcher +for a znode is disabled once it fires and user need to re-register +that watcher. During this short time znode data can be changed thus +resulting missing events. It is actually very easy to miss these +events by just changing data from a multiple threads in a concurrent +manner. + +Order to overcome this issue we're keeping individual context changes +in a multiple znodes and we just use a simple integer counter to mark +which znode is a current active one. This allows us to replay missed +events. We don't want to create more and more znodes and then later +delete old ones, instead we're using a simple concept of a circular +set of znodes. This allow use to use predefined set of znodes where +current had can be determided with a simple counter. We already have +this counter by tracking main znode data version which in zookeeper is +an integer. + +Size of a circular buffer is mandated to be a power of two not to get +trouble when interger is going to overflow thus we don't need to +handle any specific cases. + diff --git a/docs/src/reference/asciidoc/sm-examples.adoc b/docs/src/reference/asciidoc/sm-examples.adoc index 34c502bc..b9675402 100644 --- a/docs/src/reference/asciidoc/sm-examples.adoc +++ b/docs/src/reference/asciidoc/sm-examples.adoc @@ -898,8 +898,8 @@ Entry state LOCKED [[statemachine-examples-web]] == Web Web is a distributed state machine example using a zookeeper to handle -distribted state. This example is meant to be run on a multiple -browser sessions agains a multiple different hosts. +distributed state. This example is meant to be run on a multiple +browser sessions against a multiple different hosts. This sample is using a modified state machine structure from a <> to work with a distributed state @@ -911,16 +911,16 @@ Due to nature of this sample an instanse of a `Zookeeper` is expected to be available from a localhost for every individual sample instance. ==== -Lets go through a simple example where two different sample instances are +Lets go through a simple example where three different sample instances are started with command `java -jar spring-statemachine-samples-web-1.0.0.BUILD-SNAPSHOT.jar`. If you are running different instances on a same host you need to distinguish used port by adding `--server.port=` to the command. Otherwise default port for each host will be `8080`. -In this sample run we have three hosts, `n1`, `n2` and `n3`. which all -have a zookeeper running and a state machine sample running on a port -`8080`. +In this sample run we have three hosts, `n1`, `n2` and `n3` which all +have a local zookeeper instance running and a state machine sample running +on a port `8080`. [source,text] ---- @@ -929,31 +929,28 @@ have a zookeeper running and a state machine sample running on a port @n3:~# java -jar spring-statemachine-samples-web-1.0.0.BUILD-SNAPSHOT.jar ---- -Lets take a sample run of this example assuming that we have three -nodes, `n1`, `n2` and `n3` hosting `Zookeeper` and this statemachine -web sample. - When all instances are running you should see all showing similar -information via a browser where you have states `S0`, `S1` and `S11`, +information via a browser where states are `S0`, `S1` and `S11`, and extended state variable `foo=0`. Main state is `S11`. image::images/sm-dist-n1-1.png[width=500] When you press button `Event C` in any of a browser window, distributed state is changed to `S211` which is the target state -denoted by transition associated with a event `C`. +denoted by transition associated with an event `C`. image::images/sm-dist-n2-2.png[width=500] Then lets press button `Event H` and what is supposed to happen is -that internal transition is happening on all state machines changing +that internal transition is executed on all state machines changing extended stare variable `foo` from value `0` to `1`. This change is -then propagated to other state machines. You should only see variable -`foo` to change from `0` to `1`. +first done on a state machine receiving the event and then propagated +to other state machines. You should only see variable `foo` to change +from `0` to `1`. image::images/sm-dist-n3-3.png[width=500] -Last we simply send event `Event C` which is supposed to take state +Last we simply send an event `Event C` which is supposed to take state machine state back to state `S11` and you should see this happening in all browser sessions. diff --git a/docs/src/reference/asciidoc/sm.adoc b/docs/src/reference/asciidoc/sm.adoc index 6eaafb48..4e43f5de 100644 --- a/docs/src/reference/asciidoc/sm.adoc +++ b/docs/src/reference/asciidoc/sm.adoc @@ -703,6 +703,13 @@ within a single state machine is naturally really simple to understand but when there is a need to introduce a shared distributed state thoughout a state machines, things will get a little complicated. +[NOTE] +==== +Distributed state functionality is still a preview feature and is not +yet considered to be stable in this particular release. We expect this +feature to mature towards the first official release. +==== + For configuration support see section <> and actual usage example see sample <>.