Last active
August 29, 2021 11:59
-
-
Save horothesun/5e7e9e41f845def8e85491d98583405e to your computer and use it in GitHub Desktop.
Polling in Groovy (useful for Jenkins pipelines)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def <T> T poll( // can throw | |
long pollIntervalSeconds, // must be bigger than `functionToPoll()` execution time | |
long timeoutSeconds, // global timeout | |
Integer maxConsecutiveExceptionsAllowed, // maximum consecutive times `functionToPoll()` can throw before polling fails | |
Closure<T> functionToPoll, // returns T, can throw | |
Closure<Boolean> successConditionOnFnResult // returns Boolean, condition over `functionToPoll()` result to determine if polling is completed | |
) { | |
def Boolean isDone = false | |
def Boolean isTimeout = false | |
def Integer exceptionCounter = 0 | |
def T result | |
def long timeoutDateMillis = new Date().getTime() + 1000 * timeoutSeconds | |
def long pollIntervalMillis = 1000 * pollIntervalSeconds | |
while (!isDone && !isTimeout) { | |
try { | |
result = functionToPoll() | |
isDone = successConditionOnFnResult(result) | |
exceptionCounter = 0 | |
println("exceptionCounter reset") // TODO: remove π₯π₯π₯ | |
} catch(e) { | |
exceptionCounter += 1 | |
println("exceptionCounter == $exceptionCounter") // TODO: remove π₯π₯π₯ | |
if (exceptionCounter > maxConsecutiveExceptionsAllowed) { | |
throw new Exception("Polling failed: base function threw $exceptionCounter exceptions in a row. Last exception: $e.message") | |
} | |
} | |
if (!isDone) { | |
println("not isDone => sleep($pollIntervalMillis)") // TODO: remove π₯π₯π₯ | |
sleep(pollIntervalMillis) | |
} | |
isTimeout = new Date().getTime() >= timeoutDateMillis | |
} | |
println("isDone == $isDone, isTimeout == $isTimeout") // TODO: remove π₯π₯π₯ | |
if (isDone) { | |
return result | |
} | |
if (isTimeout) { | |
throw new Exception("Polling timed out after ${timeoutSeconds}s") | |
} | |
} | |
// manual testing | |
def Integer state = 6 | |
poll( | |
2, // pollIntervalSeconds | |
18, // timeoutSeconds | |
3, // maxConsecutiveExceptionsAllowed | |
{ | |
println("fake logic started... (state == $state)") | |
sleep(1 * 1000) | |
state -= 1 | |
if (state > 4 || (state > 0 && state < 4)) { | |
println("fake logic failure (exception) (state == $state)") | |
throw new Exception("fake logic throwing (state == $state)") | |
} else if (state == 4) { | |
println("fake logic failure (wrong result) (state == $state)") | |
return "wrong fake result" | |
} else { | |
println("fake logic success (state == $state)") | |
return "fake result" | |
} | |
}, | |
{ String s -> s == "fake result" } | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment