Конечно, я хочу обернуть различные запросы к внешним сервисам с помощью 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!
явно не то, что я хочу.
Есть ли лучший способ для достижения трех целей возвращающихся результата, защиты от длительных перерывов и ошибок ручки? Синтаксис вполне нормальный (большинство вещей выше, чтобы спровоцировать эти три ошибки).
oh, btw, это также доступно в командах 'трубопровод'! – claj