packages feed

happs-tutorial-0.8: templates/multimaster.st

<h3>Scaling your applications with multimaster</h3>
<p>
An obvious concern when learning that Happstack.State keeps all state in memory is scalability.  After all, that certainly seems to imply that one can only use a single Happstack instance on one machine to service your entire application.  Fortunately, this isn't the case thanks to a feature called multimaster!
</p>
<p>Multimaster is a way to synchronize state between multiple Happstack instances.  It's built atop the 
<a href="http://www.spread.org/">Spread Toolkit</a> via the 
<a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hspread">hspread</a> 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.</p>
<h4>Setting up Spread on Linux</h4>
<ol>
  <li>Download and install the Spread 4 release available <a href="http://www.spread.org/download/spread-bin-4.0.0.tar.gz">here</a>.</li>
  <li>Run the following command, using the <a href="/src/spread.conf">conf</a> file included in this tutorial, to run Spread on your local machine:  spread -c spread.conf -n localhost</li>
  <li>If you are immediately returned to the command prompt, then Spread is not actively running.</li>
</ol>
<h4>A few brief multimaster examples</h4>
<p>Copy the source code from <a href="/src/MultiExample1.hs">MultiExample1.hs</a>, 
   <a href="/src/MultiExample2.hs">MultiExample2.hs</a>, <a href="/src/MultiExample3.hs">MultiExample3.hs</a>.  
   I know this is a lot of files, but I'll walk you through them all.</p>
<ol>
  <li>Start up MultiExample1 and MultiExample2</li>
  <li>Increment the state in MultiExample1.</li>
  <li>Confirm that the changes are visible in MultiExample2.</li>
  <li>Checkpoint MultiExample1</li>
  <li>Close both programs.</li>
  <li>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.</li>
  <li>Restart one or the other and you should see the state
      as you left it.</li>
  <li>Start MultiExample3 as well.  Check that the state is synced</li>
  <li>Increment the state.  Notice the error message you get in the window running MultiExample3.</li>
  <li>Confirm that the state was not updated in MultiExample3.</li>
</ol>
<p>I'm presuming that the synchronization is fairly straight forward from the example, but why the errors in MultiExample3?</p>
<p>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!</p>
<h4>Scaling your own applications</h4>
<p>Making your own applications use multimaster is surprisingly simple!
You just need to use the function startSystemStateMultimaster.
<br>ghci>:i startSystemStateMultimaster
<br>startSystemStateMultimaster ::
<br>  (Methods a, Component a) =>
<br>  Proxy a -> IO (GHC.IOBase.MVar TxControl)
<br>        -- Defined in Happstack.State.Control
</p>
<p>To summarize, take a look at the code in <a href="/src/MultiExample1.hs">MultiExample1.hs</a>
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.</p>
<p>Now we'll talk briefly about <a href="/tutorial/macid-data-safety">MACID safety</a>.</p>