2016-10-22 159 views
3

我有下面的Groovy代码:为什么在迭代列表时需要@NonCPS?

// @NonCPS 
def printList(params) { 
    def jobs = [:] 
    println params 
    params.split(",").each { param -> 
     println "Param: ${param}" 
    } 
} 
text = "Foo,Bar,Baz,Qux" 
printList(text) 

groovy命令调用时预期其工作原理:

$ groovy test.groovy 
Foo,Bar,Baz,Qux 
Param: Foo 
Param: Bar 
Param: Baz 
Param: Qux 

尽管詹金斯非沙盒的工作中进行测试时,我有不同结果:

[Pipeline] echo 
Foo,Bar,Baz,Qux 
[Pipeline] echo 
Param: Foo 
[Pipeline] End of Pipeline 

问题是只打印第一项而不是全部打印。

但是,只有在使用@NonCPS辅助方法时,代码才能在Jenkins中按预期工作。

为什么@NonCPS对于正确迭代项目列表是必要的?没有使用@NonCPS(特别是在沙盒环境中)有什么解决方法吗?

+3

我不会尝试,现在CPS工作在流水线解释你,它的实现还是有点神奇/对我来说不可预知,并且与这个问题无关。然而,我可以说非沙盒管道的行为与同一个脚本的沙盒版本有很大不同。对我来说可能会成为实施问题。 Jenkins管道现在仍在大量开发中。顺便说一下,'禁用沙箱'选项不适用于SCM来源的scipt,原因很明显 – agg3l

+2

我建议您关注“沙盒”模式,解决它出现时的问题和限制。这是管道的主要模式 – agg3l

回答

1

尽管我很了解CPS如何工作和实现,以及如何通过管道处理它(迄今为止还没有潜入其代码中),但流水线尝试测试暂停(备份/ ..传输的能力)。 ./restore)执行(JVM)状态在大多数代码指令通过序列化接口。考虑到它是JVM < groovy <管道DSL ..这是花费很多努力实现插件开发人员。然后Groovy生成器(例如{ f -> print f })与Python(yield)或C/C++生成器(函数对象)非常相似,但我自己并不是Groovy或Java大师,Groovy生成器(例如{ f -> print f }) )。

只要可迭代的主题迭代器(例如列表索引或产量表达式状态)是隐式的,那么到目前为止,那些不能通过管道轻松序列化。 因此,Java风格循环的优先选择。

只要执行范围明确包含循环迭代器('i'索引变量),则替代Java样式(经典C)循环的处理要简单得多。

请不要认为这是一个权威的答案,上述只是我的管道CPS

1

你也可以用其他的方法来达到同样的效果的个人理解。例如,下面是序列化的,不需要@NonCPS通过一个名为MYLIST列表进行迭代:

for(int i=0; i < mylist.size(); i++) { 
    println mylist[i] 
} 
相关问题