Skip to content

Instantly share code, notes, and snippets.

@horothesun
Last active August 29, 2021 11:59
Show Gist options
  • Save horothesun/5e7e9e41f845def8e85491d98583405e to your computer and use it in GitHub Desktop.
Save horothesun/5e7e9e41f845def8e85491d98583405e to your computer and use it in GitHub Desktop.
Polling in Groovy (useful for Jenkins pipelines)
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