2012-04-12 12 views
93

Avevo creato un demone che utilizzava una forma molto primitiva di ipc (telnet e inviava una stringa con determinate parole in un determinato ordine). Ne sono uscito fuori e ora sto usando JSON per passare messaggi a un server Yesod. Tuttavia, c'erano alcune cose che mi sono piaciute molto del mio design e non sono sicuro di quali siano ora le mie scelte.Eccezioni in Yesod

Ecco quello che stavo facendo:

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

ogni funzione in buildSeq si presentava così

foo :: Stage -> ReaderT Config IO() 

data Config = MkConfig (Either JobID Product) BaseDir JobMap 

JobMap è un TMVar Map che tiene traccia delle informazioni relative ai lavori in corso.

così ora, quello che ho sono i gestori, che tutti guardano come questo

foo :: Handler RepJson 

foo rappresenta un comando per il mio demone, ogni gestore può avere per elaborare un oggetto JSON diverso.

Quello che mi piacerebbe fare è inviare un oggetto JSON che rappresenta il successo e un altro oggetto JSON che esprime informazioni su alcune eccezioni.

Vorrei foo s funzione di supporto per essere in grado di restituire un Either, ma non sono sicuro di come l'ho capito, oltre alla possibilità di interrompere la valutazione del mio elenco di azioni, buildSeq.

Ecco l'unica scelta che vedo

1) assicurarsi exceptionHandler è in Handler. Inserire JobMap nel record App. Utilizzando getYesod alterare il valore appropriato nella JobMap indicando particolari circa l'eccezione, che possono poi essere letta da foo

C'è un modo migliore?

Quali sono le mie altre scelte?

Modifica: Per chiarezza, spiegherò il ruolo di Handler RepJson. Il server ha bisogno di un modo per accettare comandi come buildstopreport. Il cliente ha bisogno di conoscere i risultati di questi comandi. Ho scelto JSON come mezzo con cui server e client comunicano tra loro. Sto usando il tipo Handler solo per gestire il JSON in/out e niente altro.

risposta

9

Filosoficamente parlando, nel mondo Haskell/Yesod si desidera inoltrare i valori piuttosto che tornare indietro. Quindi, invece di fare in modo che i gestori restituiscano un valore, invitali a chiamare il passaggio successivo del processo, che potrebbe essere quello di generare un'eccezione.

Ricorda che puoi raggruppare qualsiasi quantità di azioni future in un singolo oggetto, in modo da poter passare un oggetto di continuazione ai gestori e ai foos che in pratica dice loro: "Dopo aver terminato, esegui questo blob di codice". In questo modo possono essere nulli e non restituire nulla.

+0

Grazie per l'intuizione, Tyler Durden. –