当前位置 : 主页 > 手机开发 > 其它 >

错误处理 – 使用clojure core.async管道处理错误

来源:互联网 收集:自由互联 发布时间:2021-06-22
我试图了解使用core.async / pipeline处理错误的正确方法是什么,我的管道如下: input -- xf-run-computation -- first-outfirst-out -- xf-run-computation -- last-out 其中xf-run-computation将执行http调用并返回响应
我试图了解使用core.async / pipeline处理错误的正确方法是什么,我的管道如下:

input     --> xf-run-computation --> first-out
first-out --> xf-run-computation --> last-out

其中xf-run-computation将执行http调用并返回响应.但是,其中一些响应将返回错误.处理这些错误的最佳方法是什么?
我的解决方案是将输出通道分成成功值和错误值,然后将它们合并回通道:

(let [[success-values1 error-values1] (split fn-to-split first-out)
      [success-values2 error-values2] (split fn-to-split last-out)
      errors (merge [error-values1 error-values2])]
(pipeline 4 first-out xf-run-computation input)
(pipeline 4 last-out  xf-run-computation success-values1)
[last-out errors])

所以我的函数将返回最后的结果和错误.

一般来说,“正确”的方法可能取决于您的应用需求,但考虑到您的问题描述,我认为您需要考虑三件事:

> xf-run-computation返回业务逻辑将看作错误的数据,
> xf-run-computation抛出异常并且
>鉴于涉及到http调用,一些xf-run-computation运行可能永远不会完成(或者没有及时完成).

关于第3点,您应该考虑的第一件事是使用管道阻塞而不是管道.

我认为你的问题主要与第1点有关.基本思想是xf-run-computation的结果需要返回一个数据结构(比如地图或记录),这清楚地将结果标记为错误或成功,例如{:title nil:body nil:status“error”}.这将为您提供处理这种情况的一些选择:

>以后的所有代码都会忽略输入数据,其中包含:status“error”.即,你的xf-run-computation将包含一行(当(not(=(:status input)“error”))(运行计算输入)),
>您可以对管道调用之间的所有结果运行过滤器并根据需要对其进行过滤(请注意,过滤器也可以用作管道中的传感器,从而消除旧过滤器>并过滤< core.async的功能),
>你使用像你建议的async / split / Alan Thompson在他的回答中显示过滤掉错误值到一个单独的错误通道.如果您要合并值,则无需为第二个管道设置第二个错误通道,您只需重新使用错误通道即可.

对于第2点,问题是xf-run-computation中的任何异常都发生在另一个线程中,并且不会简单地传播回调用代码.但是你可以使用ex-handler参数来管道(和管道阻塞).您可以简单地过滤掉所有异常,将结果放在单独的异常通道上或尝试捕获它们并将它们转换为错误(可能将它们放回结果或其他错误通道) – 后者只有在例外为您提供了足够的信息,例如允许将异常绑定到导致异常的输入的id或其他内容.您可以在xf-run-computation中安排此操作(即捕获从第三方库(如http调用)抛出的任何异常).

对于第3点,core.async中的规范答案将指向超时通道,但这与管道相关没有多大意义.更好的办法是确保在您的http调用中设置超时,例如:http-kit的超时选项或:socket-timeout和:clj-http的conn-timeout.请注意,这些选项通常会导致超时异常.

网友评论