Pengecualian di Yesod

93

Saya telah membuat daemon yang menggunakan bentuk yang sangat primitif ipc(telnet dan mengirim String yang memiliki kata-kata tertentu dalam urutan tertentu). Saya membentaknya dan sekarang menggunakan JSONuntuk meneruskan pesan ke Yesodserver. Namun, ada beberapa hal yang sangat saya sukai dari desain saya, dan saya tidak yakin apa pilihan saya sekarang.

Inilah yang saya lakukan:

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

setiap fungsi di buildSeq terlihat seperti ini

foo :: Stage -> ReaderT Config IO ()

data Config = MkConfig (Either JobID Product) BaseDir JobMap

JobMapadalah TMVar Mapyang melacak informasi tentang pekerjaan saat ini.

jadi sekarang, yang saya punya adalah Penangan, semuanya terlihat seperti ini

foo :: Handler RepJson

foo mewakili perintah untuk daemon saya, setiap penangan mungkin harus memproses objek JSON yang berbeda.

Yang ingin saya lakukan adalah mengirim satu JSONobjek yang mewakili kesuksesan, dan objek JSON lain yang menekankan informasi tentang beberapa pengecualian.

Saya ingin foofungsi helper dapat mengembalikan Either, tetapi saya tidak yakin bagaimana saya mendapatkannya, ditambah kemampuan untuk menghentikan evaluasi daftar tindakan saya , buildSeq.

Inilah satu-satunya pilihan yang saya lihat

1) pastikan exceptionHandlerada di Handler. Masukan JobMapdalam Appcatatan. Menggunakan getYesodmengubah nilai yang sesuai dalam JobMapmenunjukkan detail tentang pengecualian, yang kemudian dapat diakses olehfoo

Apakah ada cara yang lebih baik?

Apa pilihan saya yang lain?

Edit: Untuk kejelasan, saya akan menjelaskan peran Handler RepJson. Server membutuhkan beberapa cara untuk menerima perintah seperti build stop report. Klien membutuhkan beberapa cara untuk mengetahui hasil dari perintah ini. Saya telah memilih JSON sebagai media yang berkomunikasi dengan server dan klien satu sama lain. Saya menggunakan tipe Handler hanya untuk mengelola JSON masuk / keluar dan tidak lebih.

Michael Litchard
sumber

Jawaban:

9

Secara filosofis, di dunia Haskell / Yesod Anda ingin meneruskan nilai-nilai ke depan, daripada mengembalikannya ke belakang. Jadi, alih-alih meminta penangan mengembalikan nilai, minta mereka memanggil maju ke langkah berikutnya dalam proses, yang mungkin menghasilkan pengecualian.

Ingatlah bahwa Anda dapat menggabungkan sejumlah tindakan mendatang ke dalam satu objek, sehingga Anda dapat meneruskan objek lanjutan ke penangan dan foo yang pada dasarnya memberi tahu mereka, "Setelah selesai, jalankan gumpalan kode ini." Dengan cara itu mereka bisa batal dan tidak mengembalikan apa-apa.

Tyler Durden
sumber