kenorb kenorb - 2 months ago 81
Groovy Question

Why @NonCPS is necessary when iterating through the list?

I've the following Groovy code:

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

which works as expected when invoking from

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

Although when testing within a non-sandboxed job in Jenkins, I've different results:

[Pipeline] echo
[Pipeline] echo
Param: Foo
[Pipeline] End of Pipeline

The problem is that only the first item is printed, instead of all.

However the code works as expected in Jenkins only when using the
helper method.

is necessary in order to iterate through the list of items properly? And is there any workaround without using
(especially in sandboxed environment)?


As much I understand how CPS works and implemented in general, and how it is handled by pipeline (hadn't dived into its code so far), pipeline attempts to test for ability to suspend (backup/..transfer../restore) execution (JVM) state at most of code instructions though serialization interface. Considering it is JVM < groovy < pipeline DSL .. that's take much effort to implement for plugin developers.

Next, not being a Groovy or Java guru myself, as much as I can think of its implementation, groovy generators (e.g. { f -> print f } ) are very much similar to those in python (yield) or C/C++ generators (functor objects).

Those cannot be serialized by pipeline with ease so far, as long as iterable subject iterator (e.g. list index or yield expression state) are implicit. Thus preference of Java-style loops.

Alternative Java-style (classic C) loops are much more simpler to handle, as long as execution scope explicitly contains loop iterator ('i' index variable).

Please don't consider this an authoritative answer, aforementioned is just my personal understanding of pipeline CPS