1. new in this version
  2. build a web 2.0 app in happstack
  3. why happstack is cool
  4. getting started with happstack
  5. prerequisites
  6. cabal install me
  7. first shot at happstack
  8. url handling
  9. basic HTML inclusion
  10. templates
  11. stringtemplate basics
  12. debugging
  13. form data: get and post
  14. form data: file uploads
  15. cookies
  16. introduction to macid
  17. first steps with macid
  18. scaling with multimaster
  19. using macid safely
  20. macid dummy data
  21. changing the data model
  22. macid stress test
  23. limitations of macid
  24. foreign characters
  25. IxSets
  26. cron jobs
  27. thanks
  28. appendix (floundering in ghci)

Scaling your applications with multimaster

When first learning that Happstack.State keeps all state information in memory, you might assume that your application must be served by a single instance running on a single machine. This is actually not the case! You can have a number of nodes each with their own copy of the state using a feature called multimaster.

Multimaster is a way to synchronize state between multiple Happstack instances. It's built atop the Spread Toolkit via the hspread bindings. Happstack does not do any set up or configuration of Spread for you. You'll need to take care of the Spread daemon yourself before attempting to run an application using multimaster. We'll be walking through an example of this set up in the case of Linux.

Setting up Spread on Linux

  1. Download and install the Spread 4 release available here.
  2. Run the following command, using the conf file included in this tutorial, to run Spread on your local machine: spread -c spread.conf -n localhost
  3. If you are immediately returned to the command prompt, then Spread is not actively running.

A few brief multimaster examples

Copy the source code from MultiExample1.hs, MultiExample2.hs, MultiExample3.hs. I know this is a lot of files, but I'll walk you through them all.

  1. Start up MultiExample1 and MultiExample2
  2. Increment the state in MultiExample1.
  3. Confirm that the changes are visible in MultiExample2.
  4. Checkpoint MultiExample1
  5. Close both programs.
  6. Check under _local and find the states recorded for each application. Note that each one is serializing its set of events separately and that a checkpoint was only made for MultiExample1. Multimaster makes sure that events are synced up, but checkpointing isn't an 'event' in this context.
  7. Restart one or the other and you should see the state as you left it.
  8. Start MultiExample3 as well. Check that the state is synced
  9. Increment the state. Notice the error message you get in the window running MultiExample3.
  10. Confirm that the state was not updated in MultiExample3.

I'm presuming that the synchronization is fairly straight forward from the example, but why the errors in MultiExample3?

If you check out the source for MultiExample3, you'll see that there's no succVal Update defined in the file. The way multimaster works is that it reroutes the events. If an application receiving the events doesn't have a registered handler, i.e. an Update made into a Method by calling mkMethod, then it won't be able to perform the Update. It won't crash, but it will fall out of sync; sometimes the latter can be worse!

Scaling your own applications

Making your own applications use multimaster is surprisingly simple! You just need to use the function startSystemStateMultimaster.
ghci>:i startSystemStateMultimaster
startSystemStateMultimaster ::
(Methods a, Component a) =>
Proxy a -> IO (GHC.IOBase.MVar TxControl)
-- Defined in Happstack.State.Control

To summarize, take a look at the code in MultiExample1.hs as a starter. Notice that all you need to do is feed a Proxy to startSystemStateMultimaster and then call simpleHTTP as normal. The back end of Happstack.State takes care of the rest.

Now we'll talk briefly about MACID safety.