Исключения в Yesod

Я создал демона, который использовал очень примитивную форму ipc (telnet и отправил String с определенными словами в определенном порядке). Я отключил его, и теперь я использую JSON для передачи сообщений на сервер Yesod. Тем не менее, были некоторые вещи, которые мне очень нравились в моем дизайне, и я не уверен, каковы мои варианты сейчас.

Вот что я делал:

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 ()

каждая функция в buildSeq выглядела так:

foo :: Stage -> ReaderT Config IO ()

data Config = MkConfig (Either JobID Product) BaseDir JobMap

JobMap - это TMVar Map, который отслеживает информацию о текущих заданиях.

Итак, теперь у меня есть обработчики, все это выглядит как

foo :: Handler RepJson

foo представляет собой команду для моего демона, каждый обработчик может обрабатывать другой объект JSON.

Мне бы хотелось отправить один объект JSON, который представляет успех, и другой объект JSON, который предоставляет информацию о некотором исключении.

Я бы хотел, чтобы вспомогательная функция foo могла возвращать Either, но я не уверен, как это получить, плюс возможность прекратить оценку моего списка действий, buildSeq.

Здесь единственный выбор, который я вижу

1) убедитесь, что exceptionHandler находится в обработчике. Поместите JobMap в запись App. Используя getYesod измените соответствующее значение в JobMap, указав сведения об исключении, к которому затем можно получить доступ foo

Есть ли лучший способ?

Каковы мои другие варианты?

Изменить: для ясности я объясню роль Handler RepJson. Серверу необходимо каким-то образом принять команды, такие как build stop report. Клиенту нужен какой-то способ узнать результаты этих команд. Я выбрал JSON как среду, с которой сервер и клиент общаются друг с другом. Я использую тип Handler только для управления JSON in/out и ничего более.

Ответ 1

Философски говоря, в мире Haskell/Yesod вы хотите передать значения вперед, а не возвращать их назад. Поэтому вместо того, чтобы обработчики возвращали значение, попросите их перезвонить на следующий шаг процесса, который может быть причиной исключения.

Помните, что вы можете связать любое количество будущих действий с одним объектом, чтобы вы могли передать объект продолжения вашим обработчикам и foos, которые в основном говорят им: "После того, как вы закончите, запустите этот код кода". Таким образом, они могут быть недействительными и ничего не возвращать.