2014-10-21 3 views
4

Конечно, я хочу обернуть различные запросы к внешним сервисам с помощью core.async, все еще возвращая результаты этих операций через некоторый chan.Более элегантный способ обработки ошибок и тайм-аутов в core.async?

Я хочу позаботиться обо всех заброшенных исключениях и тайм-аутах (т. Е. Что операция займет больше времени, чем ожидалось, или иметь возможность выбирать между различными службами для одной и той же задачи, но с разными подходами или качествами обслуживания.

Самый маленький жизнеспособный пример, чтобы показать примеры и быть в состоянии обрабатывать ошибку, тайм-аут и правильный возвращающегося результат, кажется, это:

(require '[clojure.core.async :refer [chan go timeout <! >! alt!]]) 

(def logchan (chan 1)) 

(go (loop [] 
     (when-let [v (<! logchan)] 
     (println v) 
     (recur)))) 

(dotimes [_ 10] 
    (go 
    (let [result-chan (chan 1) 
      error-chan (chan 1) 
      timeout-chan (timeout 100)] 
     (go 
     (try 
      (do (<! (timeout (rand-int 200))) 
       (>! result-chan (/ 1 (rand-int 2)))) 
      (catch Exception e (>! error-chan :error)))) 
     (>! logchan (alt! [result-chan error-chan timeout-chan] 
        ([v] (if v v :timeout))))))) 

Этот код печатает что-то вроде

1 
:error 
1 
:error 
:error 
:timeout 
:error 
:timeout 
:timeout 

Это не очень элегантный. Мне особенно не нравится способ возвращения :error и :timeout. nil -check в alt! явно не то, что я хочу.

Есть ли лучший способ для достижения трех целей возвращающихся результата, защиты от длительных перерывов и ошибок ручки? Синтаксис вполне нормальный (большинство вещей выше, чтобы спровоцировать эти три ошибки).

ответ

2

Поместите выход в один канал, ошибки и результаты.

Определение записи (карты) на наличие ошибок, таких как

(defrecord SomeError [cause context etc...])

Таким образом, ошибки будут держать соответствующую информацию.

Проверьте выход в потребителях

(if-not (instance? SomeError result) ...)

Там не один «правильный» пути, вы можете использовать паб/суб для тех же целей, проходят в одной ошибке Чана или создать несколько и асинхра/слияние их вместе.

5

core.async chan -функция имеет экс-обработчик, поэтому следующая конструкция возможно

(chan buf-or-n xform ex-handler) 

где ex-handler является функцией одного аргумента, который получает исключение. Когда функция возвращает nil, это не помещается на канал, в противном случае функция может превратить исключение в нечто жизнеспособное для данных.

+0

oh, btw, это также доступно в командах 'трубопровод'! – claj

Смежные вопросы