You can clone with
HTTPS or Subversion.
Consider this simple handler:
fooHandler :: Snap ()
fooHandler = do
liftIO $ threadDelay $ 3*1000*1000
writeBS "Foo called"
We expect this handler throws an exception since we set 1 second timeout, our computation takes at least 3 seconds.
But it doesn't. It often throws exception, most of the time writes "Foo called" message.
This is working as intended -- the guarantee you get is that the timeout exception will be thrown at "some reasonable time" after the timeout expires, but not before. Currently the timeout manager is hard-coded to wake up at most once every five seconds.
If you want finer-grained control over timeouts (i.e. accuracy better than 5 seconds) then you'll have to use the stock Haskell System.Timeout stuff, but keep in mind that you'll be adding additional load to the GHC I/O manager by doing so.
P.S.: the design tradeoff may be different here as of GHC 7.8's MIO I/O manager, but relaxing the guarantee we offer for timeouts enables us to implement this feature a lot more cheaply under current GHC than otherwise would be possible -- and yes, that has an impact on scalability.
Re-opening to remind me to document in the docstrings what the timeout functionality does and what its limitations are, i.e. if you want accurate millisecond-level guarantees for an RPC server, you'll have to implement them in some other way.
In snap-server 1.0 you will have the option of implementing this using server hooks -- the user can pass in IO actions that run during the various phases of the request/response lifecycle. The currently released snap-server only gives you visibility into the snap monad and response sending phases.