为什么在遍历列表时需要@NonCPS?
Why @NonCPS is necessary when iterating through the list?
我有以下 Groovy 代码:
// @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
尽管在 Jenkins 中的非沙盒作业中进行测试时,我得到了不同的结果:
[Pipeline] echo
Foo,Bar,Baz,Qux
[Pipeline] echo
Param: Foo
[Pipeline] End of Pipeline
问题是只打印了第一项,而不是全部。
但是,仅当使用 @NonCPS
辅助方法时,代码才能在 Jenkins 中按预期工作。
为什么需要 @NonCPS
才能正确遍历项目列表?有没有不使用 @NonCPS
的解决方法(尤其是在沙盒环境中)?
据我了解 CPS 的一般工作和实施方式,以及它是如何由管道处理的(到目前为止还没有深入研究它的代码),管道尝试测试暂停(备份)的能力/..transfer../restore) 通过序列化接口,大多数代码指令的执行 (JVM) 状态。考虑到它是 JVM < groovy < pipeline DSL .. 插件开发人员需要付出很多努力才能实现。
接下来,我自己不是 Groovy 或 Java 大师,就我能想到的实现而言,groovy 生成器(例如 { f -> print f }
)非常与 python(产量)或 C/C++ 生成器(仿函数对象)中的非常相似。
到目前为止,只要可迭代主题迭代器(例如列表索引或 yield 表达式状态)是隐式的,就无法通过管道轻松序列化它们。
因此偏好 Java 式循环。
替代 Java 风格(经典 C)循环更容易处理,只要执行范围明确包含循环迭代器('i' 索引变量)。
请不要认为这是一个权威的答案,上述只是我个人对流水线CPS的理解
您也可以使用其他方法达到同样的效果。例如,以下是可序列化的,不需要 @NonCPS 遍历名为 mylist 的列表:
for(int i=0; i < mylist.size(); i++) {
println mylist[i]
}
我有以下 Groovy 代码:
// @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
尽管在 Jenkins 中的非沙盒作业中进行测试时,我得到了不同的结果:
[Pipeline] echo
Foo,Bar,Baz,Qux
[Pipeline] echo
Param: Foo
[Pipeline] End of Pipeline
问题是只打印了第一项,而不是全部。
但是,仅当使用 @NonCPS
辅助方法时,代码才能在 Jenkins 中按预期工作。
为什么需要 @NonCPS
才能正确遍历项目列表?有没有不使用 @NonCPS
的解决方法(尤其是在沙盒环境中)?
据我了解 CPS 的一般工作和实施方式,以及它是如何由管道处理的(到目前为止还没有深入研究它的代码),管道尝试测试暂停(备份)的能力/..transfer../restore) 通过序列化接口,大多数代码指令的执行 (JVM) 状态。考虑到它是 JVM < groovy < pipeline DSL .. 插件开发人员需要付出很多努力才能实现。
接下来,我自己不是 Groovy 或 Java 大师,就我能想到的实现而言,groovy 生成器(例如 { f -> print f }
)非常与 python(产量)或 C/C++ 生成器(仿函数对象)中的非常相似。
到目前为止,只要可迭代主题迭代器(例如列表索引或 yield 表达式状态)是隐式的,就无法通过管道轻松序列化它们。 因此偏好 Java 式循环。
替代 Java 风格(经典 C)循环更容易处理,只要执行范围明确包含循环迭代器('i' 索引变量)。
请不要认为这是一个权威的答案,上述只是我个人对流水线CPS的理解
您也可以使用其他方法达到同样的效果。例如,以下是可序列化的,不需要 @NonCPS 遍历名为 mylist 的列表:
for(int i=0; i < mylist.size(); i++) {
println mylist[i]
}