Reputation: 1538
What would be the best way to collect data (such as pass/fail results) from parallel steps.
What I've reached so far:
#!groovy
def fspam(name, spam){
spam[name] = "BEEN THERE TOO"
}
// pipeline
node('slave'){
stage("test"){
targets = ["a", "b"]
def tasks = [:]
def spam = [:]
targets.each{ tasks["${it}"] = {
node('slave'){
echo "dry-run ${it}"
spam[it] = "BEEN THERE" <--- works
fspam(it) <--- fails
}
}
}
parallel tasks
print("spam")
print(spam)
}
}
But it failed with:
Also: groovy.lang.MissingPropertyException: No such property: stam for class: WorkflowScript groovy.lang.MissingPropertyException: No such property: stam for class: WorkflowScript at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
Any suggestions
Upvotes: 2
Views: 1918
Reputation: 56
Use .asSynchronized():
targets = ["a", "b"]
tasks = [:]
spam = [:].asSynchronized()
targets.each { target ->
tasks[target] = {
echo "dry-run ${target}"
spam[target] = "BEEN THERE"
fspam(target, spam) // <--- passing spam fixes the issue
}
}
parallel tasks
print("spam")
print(spam)
This guarantees that updates to the map are thread-safe. For collecting a list, you can use [].asSynchronized()
. Link
Upvotes: 4
Reputation: 1538
Well, missed an obvious solution:
#!groovy
def fspam(name, spam){
spam[name] = "BEEN THERE TOO"
}
// pipeline
node('slave'){
stage("test"){
targets = ["a", "b"]
def tasks = [:]
def spam = [:]
targets.each{ tasks["${it}"] = {
node('slave'){
echo "dry-run ${it}"
spam[it] = "BEEN THERE"
fspam(it, spam) <--- passing spam fixes the issue
}
}
}
parallel tasks
print("spam")
print(spam)
}
}
one question remains: is there better/cleaner way?(thread safety/jenkins pipeline native, etc)
Upvotes: 1