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

欢迎!有关如何使用本页面的更多信息,请参阅关于页面。

+2
Clojure CLI

https://github.com/clojure/brew-install/pull/8中描述,在我们的CI中我们需要并行运行相同项目中多个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有一个工单

我对这个问题进行调查了一下,感觉真正的麻烦是Java的mkdirs没有解释为什么目录不能创建。通常克服mkdir竞争的方法是检查EEXIST错误,如果是这个错误,就继续而不报错,因为我们知道另一进程赢得了竞争。

如果java.nio.path.createDirectories在竞争中失败了,它将抛出FileAlreadyExistsException。

我看到该仓库中的其他代码已经使用了java.nio,所以我猜测从mkdirs转换为createDirectories是可能的。

希望这对您有所帮助!
...