Monday, January 14, 2013

Stateful, but virtually stateless, thanks to event sourcing




My example application of MFlow  has two handles for two verbs: mainmenu and shopCart

addMessageFlows [(""  ,transient $ runFlow mainmenu)
                ,("shop"    ,runFlow shopCart)]



mainmenu has a set of links to different options, but because the flow is stateful, theoretically I can not address each individual option with a link:


mainmenu=   do
       setHeader stdheader
       setTimeouts 100 0
       r <- ask $ wcached "menu" 0 $ 
               wlink CountI   (b << text "increase an Int")
               <|> (p <<< wlink CountS   (b << text "increase a String"))
               <|>  br ++> wlink Action   (b << text "Example of action, executed when a widget is validated")
               <|>  br ++> wlink Select   (b << text "select options")
               <|>  br ++> wlink CheckBoxes (b << text "checkboxes")
               <|>  br ++> wlink Radio    (b << text "Radio buttons")
               <++  br <>  br <> b << text "DYNAMIC WIDGETS"
               <|>  br ++> wlink Ajax     (b << text "AJAX example")
               <|>  br ++> wlink Autocomp (b << text "autocomplete")
               <|>  br ++> wlink AutocompList (b << text "autocomplete List")
               <|>  br ++> wlink ListEdit (b << text "list edition")
               <|>  br ++> wlink Grid (b << text "grid")
               <|>  br ++> wlink TextEdit (b << text "Content Management")
               <++  br <>  br <> b << text "STATEFUL PERSISTENT FLOW"
                 <> br <>  a ! href "shop" << text "shopping"   
                 <> br <>  br <> b << text "OTHERS"

               <|>  br ++> wlink Login    (b << text "login/logout")


       case r of
             CountI    ->  clickn  0
             CountS    ->  clicks "1"
             Action    ->  actions 1
             Ajax      ->  ajaxsample
             Select    ->  options
             CheckBoxes -> checkBoxes
             TextEdit  ->  textEdit
             Grid      ->  grid
             Autocomp  ->  autocomplete1
             AutocompList -> autocompList
             ListEdit  ->  wlistEd
             Radio     ->  radio
             Login     ->  login
I have to go to the menu first to reach any option, because mainmenu ask for the menu in the first place. Ever. But this is not that way. Each option has an absolute URL and can be accessed directly from outside. It can be copied and mailed safely to other user. This link bypass the menu and go straight to the first option: http://81.169.134.95:8081/noscript?c0=CountI It may be said that, because MFlow simulates the structure of a console application, to reach the second question it is necessary to answer  the first question. But MFlow allows to express the sequence of events (the user responses) of various steps in a single URL. In the above URL,
 c0=CountI 
is the response to the menu question, so the first 'ask' will read the menu response right from the link url. It is possible to express by hand as many user responses in a single URL as I would like, but the application now only generates links with the events corresponding to the last interaction  if the request was in GET mode. That is enough to generate a link that hop over a first step of links straight to the desired option. This example has events for two steps. it chooses the "Content Management" option and  execute the first step of this option that present a login form. But this URL has been generated by hand: http://81.169.134.95:8081/noscript?p0=()&c11=TextEdit But it is may be easy to develop an 'addressable' switch that, when activates, generates addressable URLs. It also would reset parameter numbering, so that even POST requests  would navigate to pages with a addressable URL and the page will be addressable and shareable as if the flow where stateless. With this event sourcing approack,  an stateful MFlow procedure could be as stateless (or even more) than a classical web procedure.

NOTE: by design, a link to mainmenu with no parameters will go to the current user navigation point, rather that going back to the root of the navigation (the menu). 

If there is a timeout, set with setTimeout, like in this case of 100 seconds, after this time the link to mainmenu with no parameter will go to the root.

No comments: