haskell-distributed / distributed-process-platform

DEPRECATED (Cloud Haskell Platform) in favor of distributed-process-extras, distributed-process-async, distributed-process-client-server, distributed-process-registry, distributed-process-supervisor, distributed-process-task and distributed-process-execution
http://haskell-distributed.github.com
BSD 3-Clause "New" or "Revised" License
47 stars 18 forks source link

GenProcess improvements #62

Open hyperthunk opened 11 years ago

hyperthunk commented 11 years ago

There are (3) main bits to this....

  1. better support for invariants and pre/post conditions
  2. pre/post processing filter chains
  3. dynamic upgrade support

Items (1, 2) are motivated by this kind of code:

-- | Start a counter server
startCounter :: Int -> Process ProcessId
startCounter startCount =
  let server = defaultProcess {
     dispatchers = [
          handleCallIf (state (\count -> count > 10))   -- invariant
                       (\_ (_ :: Increment) ->
                            noReply_ (TerminateOther "Count > 10"))

        , handleCall handleIncrement
        , handleCall (\count (_ :: Fetch) -> reply count count)
        , handleCast (\_ Fetch -> continue 0)
        ]
    } :: ProcessDefinition State
  in spawnLocal $ start startCount init' server >> return ()
  where init' :: InitHandler Int Int
        init' count = return $ InitOk count Infinity

Quite what this 'pre/post' condition API will look like will hopefully emerge soon...

Item (3) is not a /hot code upgrade/ as it will only work with what's in the current running image, but it does provide a way to change the process definition on the fly, which is quite useful. This would, for example, allow you to dynamically assign tasks to workers in a pool, or allow you to turn on and off support for certain application level protocols. It's also quite simple to implement, as the upgrades branch demonstrates. We send a Closure (Process TerminateReason) to the server (bundled in a message) and an automatically registered handler returns ProcessUpgrade fun and that 'fun' gets evaluated and becomes the main loop. The code that uses this mechanisms calls become newState and the upgradeHandler in newState gets called with oldDefinition -> oldState.