2024 年 Clojure 状态调查!中分享您的想法。

欢迎!请参考关于页面获取有关如何使用本网站的更多信息。

+6

你好!

我一直在修复ASYNC-163这个错误,我认为我已经找到了一个快速有效的解决方案,这不需要对pipeline*函数做很多改动。

由于我是 Clojure 的新手, contribute,虽然我在 clojure.org 网站上阅读过有关它的信息。为此,已经存在一个针对该问题的现有票据,我上面已经提到了它,然而,它已被列为“不会修复”,我没有账号在那里发表评论和发送补丁,所以我决定在这里发帖。

经过研究pipeline*函数的源代码,我已经理解了任务如何在 go-threads 和通道之间传递的整个过程,并找到了一个简单的修复方法,这需要添加一个新的通道来同步作业生产者和结果消费者线程。
我在我的博客中对此错误有更详细的解释。它相当长且错综复杂,所以我认为我没有在这里重复它,这会将这个问题变得不必要地长且难以理解。解释在这里可查这里

我在这里附带了一个补丁,如果这个位置不适合这种类型的问题,请随意指导我。我已经在 REPL 中测试了各种场景,并在我的一个项目中测试了它,该项目使用常规的 pipeline-async,它运行正确。此外,它还通过了在 core.async 库中的测试,我使用lein test命令运行了这些测试。

补丁:https://andreyorst.gitlab.io/0001-fix-ASYNC-163.patch

目前,我运行async.cljs文件(带或不带我的补丁)与 CLJS 测试时遇到了一些问题,但一旦我解决了问题,我会发布更新的补丁,适用于 JVM 和 CLJS 运行时。

修订:Nov 25 2022

补丁 v2:https://andreyorst.gitlab.io/0001-fix-ASYNC-163-2.patch

此补丁包含对async.cljs的相同修复,尽管由于某种原因我无法运行测试 - 我在浏览器中遇到了《未捕获的类型错误: process.on 不是一个函数》错误。不知道缺少什么,项目的readme中只提到了需要使用lein构建并打开HTML文件。但修复方式基本上是一样的,因此应该可以正常运行。

编辑于2022年12月08日

我将修复后的pipeline*版本放入了一个名为pipeline-extras的库中。它还有所有流程序的无序列表版本,这些版本应该有更高的吞吐量,因为传送带在任意一个任务完成时间比其他任务长的情况下不会停止。

1 个答案

0

你好,那里“不会修复”是为了表明我们认为这不是一个问题,也不认为需要修复。


编辑
好吧,访问一个有限连接数量可以提供服务的服务时,这是一个问题。

在我们的产品中,有一个配置为接受最多10个同时连接的服务。

编写

(pipeline-async 10 out-chan request-fn in-chan)

会创建12个连接而不是10个,导致服务开始拒绝连接。这是一个意外的错误。

因此,在所有使用pipeline-async函数的代码中,我们必须执行(- *max-requests* 2)以避免创建服务接受之外更多的连接。

我附加的补丁确保pipeline*函数,pipeline-async内部使用它,精确地创建n个任务而不是更多,这修复了我在工作中遇到的问题。
这是一个问题。通过重新审视这个问题,你可以避免许多烦恼。我很清楚地记得有几个第一手和第二手经验,因为这个问题导致了意外的现实世界问题。意外的、未经记录的“偏离2”并行可能会导致系统出现难以诊断的问题。
不修复的原始理由可能是对问题的一种疏忽或误解。然后解释说,“n”本应表示并行spawn的数量,而不是运行spawn的进程。然而,对于spawn自身来说,并行性没有任何实用性,因为spawn始终是一个恒定时间操作。
>> 然后,有人解释说,`n`本应表示并行spawn的数目,而不是运行spawn的进程。

很有意思!然而,`pipeline`和`pipeline-blocking`都不会共享偏离2的错误,并且确切地spawn `n` 个并行进程。这是因为在工作中,消费者线程并没有将等待结果的任务卸载给另一个线程,而是自己执行。我的补丁更改了异步结果的等待方式,因此其内部行为与阻塞和计算变体相同。
是的,Andrey,我只是想提醒Alex,这种情况的wontfix可能是他们一方的误解。可能已经太晚了来修复(因为这个错误已经被用户代码通过为偏离2提供解决方案所弥补)。但是,例如,使用含有关注问题的文档字符串弃用该函数,并提供正确版本可以拯救未来的用户免于一些噩梦般的调试过程。
作为原始JIRA问题的作者,我感到有责任发表意见,呵呵 :-) 我全心全意同意lgrapenthin的最后一条评论。多年来,我还遇到过几次人们对此行为感到困惑的情况。即使你接受与其他管道函数相对的“并行性”参数的不同含义(这就是“不会修复”状态所暗示的),我仍然看不出这对调用者有什么用处。也许我们在某个地方都遗漏了什么?

无论如何,如果这是最终决定,至少应该在文档字符串中提及这一点,例如,“具有并行性n,其中n不指代af的并行调用最大数,而指代X”(在这里填充X,以便从用户的角度来看是有意义的,仍然不够100%)。可以说,“pipeline”的文档字符串也可以相应地修改,以明确两种含义的区别,以免读者混淆。

话虽如此,我宁愿弃用这个功能,并希望Andrey的实现作为其继任者(pipeline-async2?)。
...