请分享您的观点,参加2024 年 Clojure 调查问卷!

欢迎!有关本站如何运作的更多信息,请参阅关于 页。

+2
Clojure CLI

https://github.com/clojure/brew-install/pull/8 中所述,在我们的持续集成环境中,我们需要并行运行同一项目的几个 Clojure 任务。有时会发生失败,如下所示:

Refreshing classpath
Error building classpath. Can't create directory: /path/to/project/.cpcache

我的理解是,这发生在这里https://github.com/clojure/tools.deps/blob/master/src/main/clojure/clojure/tools/deps/util/io.clj#L53-56,我们首先检查目录是否存在,然后创建它。

(when-not (.exists parent)
  (when-not (.mkdirs parent)
    (let [parent-name (.getCanonicalPath parent)]
      (throw (ex-info (str "Can't create directory: " parent-name) {:dir parent-name})))))

如果另一个进程在我们检查其存在性之后成功创建它,则 .mkdirs 返回 false,并且该进程失败。可能的解决方案是再次检查目录是否存在,如 此处

(when-not (.exists parent)
  (when-not (.mkdirs parent)
    (when-not (.exists parent)
      (let [parent-name (.getCanonicalPath parent)]
        (throw (ex-info (str "Can't create directory: " parent-name) {:dir parent-name}))))))

1 答案

+1

关于这个问题,我们已经在 https://clojure.atlassian.net/browse/TDEPS-250 创建了工单。

by
我对这个问题做了一些调查,我认为这里真正的問題是Java的mkdirs沒有说明为什么文件夹创建失败。通常克服mkdir的竞态条件的方法是检查EEXIST,如果是这个错误,则继续而無错误,因为我们知道其他进程赢了竞态。

当java.nio.path.createDirectories失去竞态竞争时,它会抛出FileAlreadyExistsException。

我看到该存储库中的其他代码已经使用了java.nio,所以我认为将mkdirs转换为createDirectories是可能的。

希望这有所帮助!
...