请在 2024年Clojure调查表 中分享您的想法!

欢迎!请访问关于页面以了解更多关于这个工作的信息。

+1
tools.gitlibs

如果有两个Clojure项目并发启动,并且都需要同一个:git/url依赖项,则其中之一的项目会抛出异常。这似乎对maven依赖项没有问题。我们在本地测试和持续集成中遇到了这个问题。

最小化重现案例

mkdir gitlibs
mkdir project
echo '{:deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner" :sha "b6b3193fcc42659d7e46ecd1884a228993441182"}}}' > project/deps.edn
export GITLIBS=gitlibs
(cd project && clojure -Spath) & (cd project && clojure -Spath)

运行此命令可能会引发以下异常

克隆: https://github.com/cognitect-labs/test-runner
克隆: https://github.com/cognitect-labs/test-runner
构建类路径时发生错误。无法锁定 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config。请确保没有其他进程在锁定文件 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config.lock 上打开文件句柄,然后您可以删除锁定文件并重试。
org.eclipse.jgit.api.errors.JGitInternalException: 无法锁定 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config。请确保没有其他进程在锁定文件 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config.lock 上打开文件句柄,然后您可以删除锁定文件并重试。
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:206)
at org.eclipse.jgit.api cloned_command.call(CloneCommand.java:89)
at clojure.tools.gitlibs.impl$call_with_auth.invokeStatic(impl.clj:50)
at clojure.tools.gitlibs.impl$call_with_auth.invoke(impl.clj:41)
at clojure.tools.gitlibs.impl$git_clone_bare.invokeStatic(impl.clj:71)
at clojure.tools.gitlibs.impl$git_clone_bare.invoke(impl.clj:68)
at clojure.tools.gitlibs.impl$ensure_git_dir.invokeStatic(impl.clj:110)
at clojure.tools.gitlibs.impl$ensure_git_dir.invoke(impl.clj:100)
at clojure.tools.gitlibs$resolve.invokeStatic(gitlibs.clj:33)
at clojure.tools.gitlibs$resolve.invoke(gitlibs.clj:29)
at clojure.tools.gitlibs$procure.invokeStatic(gitlibs.clj:47)
at clojure.tools.gitlibs$procure.invoke(gitlibs.clj:41)
at clojure.tools.deps.alpha.extensions.git$eval966$fn__968.invoke(git.clj:41)
at clojure.lang.MultiFn.invoke(MultiFn.java:239)
at clojure.tools.deps.alpha$expand_deps.invokeStatic(alpha.clj:181)
at clojure.tools.deps.alpha$expand_deps.invoke(alpha.clj:164)
at clojure.tools.deps.alpha$resolve_deps.invokeStatic(alpha.clj:231)
at clojure.tools.deps.alpha$resolve_deps.invoke(alpha.clj:213)
at clojure.tools.deps.alpha.script.make_classpath$create_classpath.invokeStatic(make_classpath.clj:61)
at clojure.tools.deps.alpha.script.make_classpath$create_classpath.invoke(make_classpath.clj:53)
at clojure.tools.deps.alpha.script.make_classpath$run.invokeStatic(make_classpath.clj:79)
at clojure.tools.deps.alpha.script.make_classpath$run.invoke(make_classpath.clj:72)
at clojure.tools.deps.alpha.script.make_classpath$_main.invokeStatic(make_classpath.clj:118)
at clojure.tools.deps.alpha.script.make_classpath$_main.doInvoke(make_classpath.clj:93)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.core$apply.invokeStatic(core.clj:665)
at clojure.main$main_opt.invokeStatic(main.clj:514)
在clojure.main$main_opt.invoke(main.clj:510)
在clojure.main$main.invokeStatic(main.clj:664)
在clojure.main$main.doInvoke(main.clj:616)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
在clojure.main.main(main.java:40)

原因:org.eclipse.jgit.errors.LockFailedException: 无法锁定 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config。请确保没有其他进程正在打开锁定文件 /home/sean/tmp/project/gitlibs/_repos/github.com/cognitect-labs/test-runner/config.lock 的文件句柄,然后您可以删除锁定文件并重试。
在org.eclipse.jgit.storage.file.FileBasedConfig.save(FileBasedConfig.java:209)
在org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:294)
在org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:200)
... 33 更多

我不确定最佳解决方案是什么。一种简单的方法是在 clojure.tools.gitlibs.impl/call-with-auth 中获取一个阻塞文件锁定。

例如,在克隆或检出 $GITLIBS/_repos/github.com/cognitect-labs/test-runner 时,clojure.tools.gitlibs 可以对 $GITLIBS/_repos/github.com/cognitect-labs/test-runner.lock 获取文件锁定。

我很乐意按照这个思路提出一个补丁。

1 答案

+1

是的,我知道这个问题,我们已经在 tools.deps 的并发下载上下文中跟踪此问题。我认为在升级到更新的 jgit 以及更了解 jgit 的工作方式之前,我们还有一些工作要做。(或者,可以考虑使用 git 的命令行操作,这可能有一组完全不同的需求和选项。)这是我们最终会解决的问题,但我认为它与这些其他事情有关,不能完全独立进行。

作为一种解决方案,您现在可以使用带有 -Sthreads 1 的 tools.deps / clj 来防止并发下载。

...