stackmob/scalamachine — pull request #7 by jrwest (2012-07-31 06:36:30+00:00)
Title: Core Rewrite (Part #I've Lost Count -- For the Future) 

#### This is still a WIP.

A redesign of the core decision & resource model that more closely resembles one of my initial implementation attempts I never got working correctly (partially due to a Scala compiler bug I was not aware of), address some issues I've noticed since using Scalamachine the past couple months and has some other benefits over the "original" implementation (there have been several, but I'm referring to the one thats been in master for a while now).

Advantages over the original:

* **No moar vars!!** - The webmachine resource context was originally modeled by using classes as resources and using vars. The original model ensured that each time a resource was served a new resource was instantiated. This is no longer necessary as context is now modeled as part of the webmachine flow state.
Each Resource has a type member `Context` which it can use to specify the type of its context (each resource can have its own Context). The context can be immutable and is manipulated via `State` actions. The resource is given the opportunity to provide an initial state. This means that resources can be `object`s and if they are classes they are only instantiated once. This greatly reduces allocation/memory costs.
* **Monad transformer stack** - monad transformers are now deeply engrained. Each resource returns a `Resource.Result`, a monad transformer stack composing the `State`, `Res` and `IO` monads. This gives each `Resource` function the ability to read and write request/response & context state, perform side effects and halt the webmachine. One annoyance of the original implementation was that the resource was the `IO` border and thus several `Resource` functions would make calls to `unsafePerformIO`. In this new model the webmachine spits out an `IO[ReqRespData]`. Additionally, it greatly simplifies the implementation in a few places. Finally, in the future, we can a) use the type system to communicate where side-effects should not be used or where the webmachine cannot be halted b) can define simpler resource interfaces (including the original one -- meaning you can still not deal with scalaz if you really want -- although it will be a bit more annoying) for resources that dont need side-effects, etc.
* **Clearer evaluation rules** - the original implementation suffered form ambiguous evaluation rules in that you could build lazy state actions but had to evaluate them in each `Resource` function. Additionally, each decision in turn returned a state action that was immediately evaluated by the flow runner. In the new model the entire flow is evaluated lazily. As mentioned previously, the webmachine returns an `IO[ReqRespData]` meaning that nothing has yet to be evaluated and no side-effects will be performed until the host framework implementation ultimately calls `unsafePerformIO`.

Costs/Tradeoffs/What have you:

* **Only Scala 2.10 will be supported** -- dependent method types are official! (2.9.2 may be possible but I haven't tested if it has the same bug with `-Ydependent-method-types` as 2.9.1 -- https://issues.scala-lang.org/browse/SI-5033)
* **Only scalaz7 will be supported** - since the monad transformer stack is pretty much engrained now supported 6 and 7 would be a nightmare if even possible (i have not really investigated and don't plan to). The utilty projects have been removed, the core has been made to depend on the official scalaz7 (milestone 1 for now) and the core has been updated a bit to account for differences between it and the scalaz7 utility project.
* The implementation in a few places got a tad bit more verbose because dependent method types made it a bit harder to abstract over decisions as was done previously with `Decision.apply`. This is mostly inconsequential as the decision implementations will change infrequently and are still rather simple.
* Some of the host framework projects may not be supported until 2.10-M6+ versions are available (thankfully netty is a java project and this won't really matter)

Still TODO:

* remove evaluation of serve expression on each dispatch (remove by-name param)
* Rewrite FlowRunnerSpecs for the new style webmachine -- they are currently commented out
* Fix DispatchTable -- its currently just broken waiting to be integrated with the new flow runner
* Adjust host framework implementations (for ones with 2.10 versions published) for DispatchTable changes
* documentation will need a giant overhaul