Exceptions dans Yesod

93

J'avais créé un démon qui utilisait une forme très primitive de ipc(telnet et envoyer une chaîne contenant certains mots dans un certain ordre). Je m'en suis sorti et j'utilise maintenant JSONpour passer des messages à un Yesodserveur. Cependant, il y avait certaines choses que j'aimais vraiment dans mon design, et je ne sais pas quels sont mes choix maintenant.

Voici ce que je faisais:

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

chaque fonction de buildSeq ressemblait à ceci

foo :: Stage -> ReaderT Config IO ()

data Config = MkConfig (Either JobID Product) BaseDir JobMap

JobMapest un TMVar Mapqui suit les informations sur les travaux en cours.

alors maintenant, ce que j'ai, ce sont des Handlers, qui ressemblent tous à ça

foo :: Handler RepJson

foo représente une commande pour mon démon, chaque gestionnaire devra peut-être traiter un objet JSON différent.

Ce que je voudrais faire, c'est envoyer un JSONobjet qui représente le succès et un autre objet JSON qui exprime des informations sur une exception.

Je voudrais foola fonction d'aide de pouvoir retourner un Either, mais je ne sais pas comment je reçois que, plus la possibilité de mettre fin à l' évaluation de ma liste d'actions, buildSeq.

Voici le seul choix que je vois

1) assurez-vous qu'il exceptionHandlerest dans Handler. Mettez JobMapdans le Appdossier. En utilisant getYesodmodifier la valeur appropriée pour JobMapindiquer les détails de l'exception, qui peuvent ensuite être consultés parfoo

Y a-t-il un meilleur moyen?

Quels sont mes autres choix?

Edit: Pour plus de clarté, je vais expliquer le rôle de Handler RepJson. Le serveur a besoin d'un moyen d'accepter des commandes telles que build stop report. Le client a besoin d'un moyen de connaître les résultats de ces commandes. J'ai choisi JSON comme support avec lequel le serveur et le client communiquent entre eux. J'utilise le type Handler juste pour gérer l'entrée / sortie JSON et rien de plus.

Michael Litchard
la source

Réponses:

9

Philosophiquement parlant, dans le monde Haskell / Yesod, vous voulez faire passer les valeurs en avant, plutôt que les renvoyer en arrière. Ainsi, au lieu de demander aux gestionnaires de renvoyer une valeur, demandez-leur de passer à l'étape suivante du processus, qui peut être de générer une exception.

N'oubliez pas que vous pouvez regrouper n'importe quelle quantité d'actions futures dans un seul objet, de sorte que vous pouvez passer un objet de continuation à vos gestionnaires et à vos foos qui leur dit essentiellement: "Une fois que vous avez terminé, exécutez ce blob de code." De cette façon, ils peuvent être nuls et ne rien rendre.

Tyler Durden
la source