Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"
printList(text)

which works as expected when invoking from groovy command:

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

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

[Pipeline] echo
Foo,Bar,Baz,Qux
[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 @NonCPS helper method.

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

like image 886
kenorb Avatar asked Nov 15 '25 21:11

kenorb


2 Answers

You can also use other methods to get the same effect. For example, the following is serializable and does not require @NonCPS to iterate through a list named mylist:

for(int i=0; i < mylist.size(); i++) {
  println mylist[i]
}
like image 58
Peter McNab Avatar answered Nov 18 '25 12:11

Peter McNab


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

like image 33
agg3l Avatar answered Nov 18 '25 13:11

agg3l



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!