Exceções em Yesod

93

Eu tinha feito um daemon que usava uma forma muito primitiva de ipc(telnet e enviar uma String que tinha certas palavras em uma determinada ordem). Eu saí dessa situação e agora estou usando JSONpara passar mensagens para um Yesodservidor. No entanto, houve algumas coisas que realmente gostei no meu design, e não tenho certeza de quais são minhas escolhas agora.

Aqui está o que eu estava fazendo:

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

cada função em buildSeq parecia com isso

foo :: Stage -> ReaderT Config IO ()

data Config = MkConfig (Either JobID Product) BaseDir JobMap

JobMapé um TMVar Mapque rastreia informações sobre os empregos atuais.

então agora, o que eu tenho são manipuladores, que se parecem com isso

foo :: Handler RepJson

foo representa um comando para meu daemon, cada manipulador pode ter que processar um objeto JSON diferente.

O que eu gostaria de fazer é enviar um JSONobjeto que representa o sucesso e outro objeto JSON que expressa informações sobre alguma exceção.

Gostaria que fooa função auxiliar pudesse retornar um Either, mas não tenho certeza de como faço isso, além da capacidade de encerrar a avaliação da minha lista de ações buildSeq,.

Aqui está a única escolha que vejo

1) certifique-se de que exceptionHandlerestá no Handler. Coloque JobMapno Appregistro. Usando getYesodalter o valor apropriado para JobMapindicar detalhes sobre a exceção, que pode então ser acessado porfoo

Existe uma maneira melhor?

Quais são minhas outras opções?

Edit: Para maior clareza, explicarei o papel de Handler RepJson. O servidor precisa de alguma forma de aceitar comandos como build stop report. O cliente precisa de alguma forma de saber os resultados desses comandos. Escolhi JSON como o meio pelo qual o servidor e o cliente se comunicam. Estou usando o tipo Handler apenas para gerenciar a entrada / saída JSON e nada mais.

Michael Litchard
fonte

Respostas:

9

Filosoficamente falando, no mundo Haskell / Yesod você deseja passar os valores adiante, em vez de devolvê-los ao contrário. Portanto, em vez de fazer com que os manipuladores retornem um valor, faça com que chamem encaminhamentos para a próxima etapa do processo, que pode ser para gerar uma exceção.

Lembre-se de que você pode agrupar qualquer quantidade de ações futuras em um único objeto, portanto, pode passar um objeto de continuação para seus manipuladores e foos que basicamente diz a eles: "Depois de terminar, execute este blob de código." Dessa forma, eles podem ser anulados e não retornar nada.

Tyler Durden
fonte