加载groovy文件时捕获异常



我有这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的例外?

问题1

Groovy闭包捕获其作用域之外的变量的方式让您着迷。闭包内对script的引用将在运行闭包时接收script的值,这将是script最后一个值。因此,两个闭包实际上都加载了"B.groovy">,并且从未抛出异常!

修复很简单,只需在循环内部创建一个局部变量,即可捕获script:的当前值

for( script in scripts ) {
def theScript = script
// Now only use theScript inside of the closure!
}

问题2

您没有从parallel线程序列化对status变量的写访问。这可能会导致非常恶劣、难以繁殖的虫子。

修复方法是使用Map.asSynchronized()创建一个同步映射:

status = [:].asSynchronized()

完成"main.groovy"修复

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}"
}

注意:我还删除了不必要的字符串插值。