我有以下3个groovy文件:
A.groovy:
// ...
stage("Test")
{
throw new Exception("This script fails")
}
B.groovy:
// ...
stage("Test")
{
// Nothing, want this to pass
}
main.groovy:
// ...
m = [:]
status = [:]
scripts = ["A", "B"]
for script in scripts
{
m["${script}"] =
{
stage("${script}")
{
try
{
load "${script}.groovy"
status["${script}"] = true
}
catch (Exception e)
{
status["${script}"] = false
}
}
}
}
parallel m
for result_iterator in status:
print "${result_iterator.key} resulted in ${result_iterator.value}"
上面的代码是真实代码的草图=) 当我运行main.groovy在状态字典中查看结果时,我只会看到B。A抛出异常,因此它没有将自身添加到字典中。我有办法以某种方式捕获A的异常吗?
答案 0 :(得分:3)
您被Groovy闭包捕获超出其范围的变量的方式所困扰。闭包内部对script
的引用将在运行闭包时收到script
的值,即script
的最后一个值。因此,这两个闭包实际上都加载“ B.groovy” ,并且永远不会引发异常!
修复很简单,只需在循环内部创建一个捕获script
当前值的局部变量即可:
for( script in scripts ) {
def theScript = script
// Now only use theScript inside of the closure!
}
您没有从status
线程序列化对parallel
变量的写访问。这可能会导致非常令人讨厌且难以复制的错误。
解决方法是使用Map.asSynchronized()
创建一个synchronized map:
status = [:].asSynchronized()
m = [:]
status = [:].asSynchronized() // because multiple threads write to this variable
scripts = ["A", "B"]
for( script in scripts ) {
def theScript = script // Important to pass the current value into the closure!
m[ theScript ] = {
stage( theScript ) {
try {
load "${theScript}.groovy"
status[ theScript ] = true
}
catch (Exception e) {
status[ theScript ] = false
}
}
}
}
parallel m
for( result_iterator in status ) {
print "${result_iterator.key} resulted in ${result_iterator.value}"
}
注意:我还删除了不必要的字符串插值。