Exceptions in Yesod
JsonHaskellException HandlingYesodJson Problem Overview
I had made a daemon that used a very primitive form of ipc
(telnet and send a String that had certain words in a certain order). I snapped out of it and am now using JSON
to pass messages to a Yesod
server. However, there were some things I really liked about my design, and I'm not sure what my choices are now.
Here's what I was doing:
buildManager :: Phase -> IO ()
buildManager phase = do
let buildSeq = findSeq phase
jid = JobID $ pack "8"
config = MkConfig $ Just jid
flip C.catch exceptionHandler $
runReaderT (sequence_ $ buildSeq <*> stages) config
-- ^^ I would really like to keep the above line of code, or something like it.
return ()
each function in buildSeq looked like this
foo :: Stage -> ReaderT Config IO ()
data Config = MkConfig (Either JobID Product) BaseDir JobMap
JobMap
is a TMVar Map
that tracks information about current jobs.
so now, what I have are Handlers, that all look like this
foo :: Handler RepJson
foo
represents a command for my daemon, each handler may have to process a different JSON object.
What I would like to do is send one JSON
object that represents success, and another JSON object that espresses information about some exception.
I would like foo
s helper function to be able to return an Either
, but I'm not sure how I get that, plus the ability to terminate evaluation of my list of actions, buildSeq
.
Here's the only choice I see
- make sure
exceptionHandler
is in Handler. PutJobMap
in theApp
record. UsinggetYesod
alter the appropriate value inJobMap
indicating details about the exception, which can then be accessed byfoo
Is there a better way?
What are my other choices?
Edit: For clarity, I will explain the role ofHandler RepJson
. The server needs some way to accept commands such as build
stop
report
. The client needs some way of knowing the results of these commands. I have chosen JSON as the medium with which the server and client communicate with each other. I'm using the Handler type just to manage the JSON in/out and nothing more.
Json Solutions
Solution 1 - Json
Philosophically speaking, in the Haskell/Yesod world you want to pass the values forward, rather than return them backwards. So instead of having the handlers return a value, have them call forwards to the next step in the process, which may be to generate an exception.
Remember that you can bundle any amount of future actions into a single object, so you can pass a continuation object to your handlers and foos that basically tells them, "After you are done, run this blob of code." That way they can be void and return nothing.