9

Wykonujemy dynamiczne tworzenie równoległych kroków w niektórych z naszych zadań. Dzięki this thread znalazłem sposób dynamicznego tworzenia mapy z parametrami do użycia w kroku równoległym.Zamykanie groovy Zamknięcie CPS do równoległego wykonania

Jednak teraz chciałem ponownie użyć części kodu, który jest używany do utworzenia tych równoległych kroków. Do tego czuję, że potrzebowałbym curry zamknięcia.

Jednak curry nie działa poprawnie. Odwoływanie się do zmiennej pętli (valueCopy) w zamknięciu robi właściwą rzecz (as mentioned here), ale curry nie robi tego, czego oczekiwałbym.

Czy robię coś złego, czy to nie jest (jeszcze) obsługiwane, czy są jakieś obejścia? Czy to prawdopodobnie błąd w potoku Jenkinsa?

Mam nadzieję, że ktokolwiek ma pojęcie, dlaczego to nie działa i/lub jak to działa.

Jenkins: LTS (2.32.1) & najnowsze aktualizacje wtyczki od 2017/01/19.

Pipeline skrypt wykonywany:

def echoSome (val) {echo val }

def buildClosures() { 
    def someList = ["1", "2", "3"] 
    def closures = [:] 
    for (value in someList) { 
     final valueCopy = value 

     closures[value] = {val -> 
       echo valueCopy.toString() 
       echo val.toString() 
      }.curry(value) 
    } 
    closures 
} 

parallel buildClosures() 

wyjściowa:

[Pipeline] parallel 
[Pipeline] [1] { (Branch: 1) 
[Pipeline] [2] { (Branch: 2) 
[Pipeline] [3] { (Branch: 3) 
[Pipeline] [1] echo 
[1] 1 
[Pipeline] [1] echo 
[1] 3 
[Pipeline] [1] } 
[Pipeline] [2] echo 
[2] 2 
[Pipeline] [2] echo 
[2] 3 
[Pipeline] [2] } 
[Pipeline] [3] echo 
[3] 3 
[Pipeline] [3] echo 
[3] 3 
[Pipeline] [3] } 
[Pipeline] // parallel 
[Pipeline] End of Pipeline 
Finished: SUCCESS 

oczekiwany wynik:

[Pipeline] parallel 
[Pipeline] [1] { (Branch: 1) 
[Pipeline] [2] { (Branch: 2) 
[Pipeline] [3] { (Branch: 3) 
[Pipeline] [1] echo 
[1] 1 
[Pipeline] [1] echo 
[1] 1 
[Pipeline] [1] } 
[Pipeline] [2] echo 
[2] 2 
[Pipeline] [2] echo 
[2] 2 
[Pipeline] [2] } 
[Pipeline] [3] echo 
[3] 3 
[Pipeline] [3] echo 
[3] 3 
[Pipeline] [3] } 
[Pipeline] // parallel 
[Pipeline] End of Pipeline 
Finished: SUCCESS 

Odpowiedz

0

Stwierdzono, że wraz z najnowszym Pipeline: Groovy wtyczki (2,40) w połączeniu z co najmniej Jenkins wersji 2.60.3 (działa chociaż stany wtyczki startowa że trzeba co najmniej Jenkins 2.73.3) wszystko działa jak spodziewany.

4

Nie jestem pewien, czy jest to Zmiękczanie lub dla pętli, ale funkcja ta musi być oznaczona jako NonCPS jak opisano tutaj: https://github.com/jenkinsci/pipeline-examples/blob/master/docs/BEST_PRACTICES.md#groovy-gotchas

Zasadniczo to zrobić:

@NonCPS 
def buildClosures() { 
    def someList = ["1", "2", "3"] 
    def closures = [:] 
    for (value in someList) { 
     final valueCopy = value 

     closures[value] = {val -> 
       echo valueCopy.toString() 
       echo val.toString() 
      }.curry(value) 
    } 
    closures 
} 

myślę, że to pętlę for, ale niezależnie od tego, kiedy nie używasz klasycznych pętli "C Style", musisz oznaczyć swoją funkcję jako NonCPS.

+0

Dzięki za odpowiedź. Z jakiegoś powodu nie zostałem powiadomiony :(Postaram się jak najszybciej. –

+0

Oznaczony jako rozwiązany, to naprawdę rozwiązuje moje pytanie. Niestety, zapomniałem wspomnieć, że oczywiście chciałbym użyć kodu CPS wewnątrz równoległe zamknięcia :( –

0

To wydaje się być ograniczeniem zarówno języka Groovy, jak i Jenkins groovy Runtime, nie jestem pewien którego, ale warto zauważyć, że ich przykłady robią dokładnie tak, jak zrobiliście, deklarując nową zmienną dla każdej iteracji pętla.

Oni pisali swój przykład

// świeże zmiennej za iteracji; Będę zmutowany

Nie sądzę, że używanie pętli w stylu C usunie to ograniczenie i currying (które byłoby wymagane w tym przypadku użycia) również nie rozwiązuje problemu. Niezdarne, ale łatwe do obejścia.

https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#creating-multiple-threads

Powiązane problemy