MFlow       Stateful, RESTful, scalable  architecture and web framework written in Haskell. MFlow is different
 This release: 9/04/2014.  agocorona@gmail.com (@agocorona) <>< . issues & bugs .  Mflow Source code,     source code of this site




New!

10+ things that you can do with MFlow and you can't with your Web framework

  1. Create test, integrate and install your logic without concern for layout. Edit your forms, widgets, style and content at run time.
  2. Convert your application from an active, single page app to multiple pages and back with little code modifications.
  3. Make forms that change the questions depending on your answers.
  4. Make a cascade menu with dynamic options programmatically, in a single procedure.
  5. Make an element of a page to refresh itself independently by adding a single statement.
  6. Convert an element of a page to present its content in push mode with a simple modifier.
  7. Press back as many times as you like by default and get what you expected.
  8. Write a multi-page flow -for example, a shopping cart checkout- and seamlessly reuse it whenever you need it.
  9. Write an active page element with his own server code, JS, CSS in a single procedure and seamlessly reuse it whenever you need it.
  10. Write your routes and control logic as in a console application. No spaguetti callback code.
  11. Transparently manage user session as normal program variables No lockups 
  12. transparently maintain the user session data for as long as you wish. even after shutdowns
  13. Have automatic persistence for your data for rapid testing of your prototype.
  14. Make all of this without writing a single line of javaScript code. Although you can add it for your own needs.
  15. Make all of this in a type safe way: If your app compiles, it works.
  16. Make (almost) all of this work with or without javascript activated.
  17. Make all of this in an architecture that is horizontally scalable (although not implemented such scalabiltiy yet)
  18. Use MFlow as an integration, orchestration and Workflow platform for your company needs.


More power and flexibility. Less plumbing. Less moving parts. 


You don't need to know Haskell before start learning MFlow. 

You will probably understand intuitively what this complete program does:

  import MFlow.Wai.Blaze.Html.All

  main= runNavigation "" . step $ do
       n  <- page $ getInt Nothing <** submitButton "first"
       n' <- page $ getInt Nothing <** submitButton "second"
       page $ p << ( n+n') ++> wlink () << b << "One more time"

What you are waiting for?

How to install MFlow
Quick Start    : Basics for understanding and using MFlow
Quick Start 2 : How to modify an application to add dynamic effects: implicit ajax, push etc.

Almost new: 

Older news 

witerate and dField. are modifiers that permit fast updates of placeholders within a page for single page applications. That is poweful specially in combination with runtime templates. All of that with standard applicative and monadic combinators. No javascript programming is necessary. All in composable, type safe haskell components (see this for a detailed explanation). The release (10/15/13) added runtime templates. it  is possible to modify the layout of the active components at run-time. This means that no longer is necessary to define a layout before compilation for a formulary,  or for the arrangement of different widgets. 

Just create them without layout, add static content after installation, when the application has been already tested. Then the layout never pollutes the code, and it may be decoupled also in time. see this

See them in action in the runtime templates example.

This demo has also cascade menus  (the main menu) implemented using monadic widgets. by simply combining applicative and monadic combinators. No Javascript is necessary. 

   autoRefresh $ ul <<< do
            li <<< wlink OptionA << "option A"
            ul <<< li <<< (wlink OptionA1 << "Option A1" <! noAutoRefresh)
               <|> li <<< (wlink OptionA2 << "Option A2" <! noAutoRefresh)
 
When the link "Option A" is clicked, the two sub-options appear. The link perform a round-trip to the server so the options can be dinamically generated. However, caching can be easilly using to avoid this round-trip if the content does not change. 


The release (8/27/13), added a powerful and improved content management facility with tFieldEd

MFlow content can be changed at runtime. All this document has been generated at run-time. I'm typing this over the application running. The programmer can specify for each content, which user can modify it. Now each content has a full text editor, it can upload images and can edit large chunks of text. See the content management example. Runtime Templates extend this capability.

This functionality uses NicEdit.

This image show this same page in edition mode with three editors for the three tFieldEd of the page.



Additionally for text areas and input fields, there is a rich editor with programmer defined controls that is included automatically inf the input field is prefixed with htmlEdit. The database example has a textarea with rich text edition.

So what is MFlow?

MFlow is simply the most high level, most advanced and fun to program web framework.  MFlow uses Haskell magic to counteract the wicked magic of the inversion of control, where the web server call the application in unpredictable ways, and the programmer has to figure out what happens and reconstruct the context by hand. The Web programmer work is terrified by an explosion of events, configurations, plumbing, lookups and identifiers dispersed in different methods, files, formats and configurations. MFlow restore web programming to his intuitive and natural way again by bringing the programmer a safe and predictable context with all his data and context available in a single piece of code where all that happens is in front of his eyes.


Everything in MFlow that seems sophisticated is to solve a user problem, not a way to hide with fancy names the inherent flawed nature of the MVC model when used in real web applications.


MFlow Web applications are much like console applications. You just write an ordinary sequential program with inputs, outputs and control statements where the inputs and outputs are web pages. MFlow will run the sequence forward and backward depending on your input to find the appropriate location in the sequence to respond your query. 


MFlow works in the same way people would read a cooking recipe: Each person look for instructions forward or backward until they find the correct point in the sequence appropriate for his state in the cooking process. To know his state, the people remember the name of the steps already done, but not the details of each step. That is exactly what MFlow does. All is pure tracking, backtracking and event logging.

Other frameworks try to do it with heavy page state or execution state snapshots That is too bad for scalability and this has limited the acceptance of this model for large scale web applications.


Additionally MFlow has nice unique features for the creation of rich and dynamic applications: widgets can exhibit dinamic behaviours and refresh independently on their own without using explicit javaScript. The code for these dynamic widgets are, again much like console applications. With a few changes, a multi-page application can be converted into a dynamic auto-refreshed widget that can be inserted in a page along with others.


MFlow is the only Web Framework that uses matching of requests and true backtracking as the mechanism for browser-server synchronization. Each link or form in the page return type safe responses. The navigation is also type safe since it is encoded within a monadic procedure. The server process ever synchronize with the browser request. There are no sequence errors. The page is composed of reusable type-safe components called widgets that may change their rendering depending o the user responses by auto refreshing themselves  without using JavaScript.


Since the navigation is coded as a normal procedure under the navigation monad, any navigation sequence can be reusable. Deployment and configuration is reduced to zero. The elements can work together if they type-check. In the examples you will see different ways to combine components: either widgets inside widgets, different widgets in a page or complete application flows called as normal procedures in a program.


Motivation:

MFlow was an application server designed for creating and execute complex workflows with a massive quantity of user and with high peaks in highly decentralized systems and with long time span. That is the environment of the votation system necessary for the Friction-free Democracy project. This implies strong requirements for scalability, state persistence and verifiability.

Note for advanced haskellers: With creating workflows I mean just that: A way to create a workflow by means of a succession of web pages with different options. each page depend on the previous data entered. See this post to understand the requirement

About the growing trend of client side frameworks, see this

These requirements are quite general and apply to many modern applications. The architecture satisfy these requirement although some of them only theoretically at this moment, I was seduced by the elegance of the solution, so I tried to develop it as a complete web framework for general usage, with the following goals:

Goals:

  • To invert back the inversion of control of web applications and turn web programming into ordinary, intuitive, imperative-like, programming, as seen by the programmer.

  • At the same time, to maintain for the user all the freedom that he has in web applications. Back buttons and bookmarked URLs must work.

  • For scalability-sensitive applications, to avoid the fat state snapshots that continuation based frameworks need to cope with these two previous requirements. State replication and horizontal scalability must be possible.

  • For REST advocates, to maintain the elegant notation of REST URLs and the statelessness of GET requests.

  • For expert haskell programmers, to reuse the already existent web libraries and techniques.

  • For beginner programmers and for Software Engineers, to provide with a high level DSL of reusable, self contained widgets for the user interface, and multipage procedures that can work together provided that they statically typecheck, with zero configuration.

  • For highly interactive applications, to give dynamic widgets that have their own dynamic behaviors in the page, and communicate with the server with ajax, without the need of explicit JavaScript programming.
  • Separation of layout and programming when necessary. HTML layout and content modifiable in editor mode and design mode at runtime.
  • To do all with a single paradigm and composable elements, with no ad-hoc constructions for each functionality. A component can be used in different contexts: either multipage or single page applications, with or without AJAX.

How it works:

MFlow solves the first goals using an innovative approach. The routes are expressed as normal, monadic haskell code in the navigation monad. Local links point to alternative routes within this monadic computation just like a textual menu in a console application with print and read can redirect to one or other code depending on the user input. But unlike in the case of a console application the user ever has te option of press the back button and go back go to the menu back again. Any GET page is directly reachable by means of an URL.


At any moment the flow can respond to the back button or to any RESTful path that the user may paste in the navigation bar. If the procedure is waiting for another different page, the navigation monad backtrack until the path partially match. From this position on, the execution goes forward until the rest of the path match. Thus, no matter the previous state of the server process, it recover the state of execution appropriate for the request. This way the server process is virtually stateless for any GET request. However, it is possible to store a session state, which may backtrack or not when the navigation goes back and forth. It is up to the programmer to decide.


When the state matters, and user interactions can last for long, such are shopping carts, it uses a log for thread state persistence. The server process shut itself down after a programmer defined timeout. Once a new request of the same user arrive, the log is used to recover the process state. There is no need to store a snapshot of every continuation, just the result of each step. As a result, the overhead of state synchronization with persistent storage and among machines is light. The memory footprint is also low since the timeout-recovery mechnism clear the idle processes from memory.


Data tier:

State consistence and transactions are given by the TCache package.

It is data cache within the STM monad (Software Transactional Memory). Serialization and deserialization of data is programmer defined, so it can adapt it to any database, although any other database interface can be used. Default persistence in files comes out of the box for rapid development purposes.


MFlow has bindings also for Amazon Web Services and Persistent. This latter is backend-independent, developed for the Yesod web Framework. 


Persistent allow MFlow to ease the connection to different SQL databases and other NoSQL databases such is MongoDB.


Demos:


Widgets:

The processes interact through widgets, that are an extension of formlets with additional applicative combinators , formatting, link management, callbacks, modifiers, caching and AJAX. All is coded in pure haskell. Each widget return statically typed data. They can dynamically modify themselves using AJAX internally (Just prefix it with autorefresh). They are auto-contained: they may include their own JavaScript code, server code and client code in a single pure Haskell procedure that can be combined with other widgets with no other external configuration needed.

To combine widgets, applicative combinators are used. Widgets with dynamic behaviours can use the monadic syntax and callbacks.


Modularity:

The interfaces and communications are abstract, but there are bindings for blaze-html, HSP, Text.XHtml and byteString, Hack and WAI but it can be extended to non Web based architectures.

It is designed for applications that can be run with no deployment within runghc in order to speed up the development process. see this.



comments powered by Disqus