Jonathan De Leon
04/27/2022, 7:18 PMSchedule to repeat an operation. Is there a way to get the delay after adding jitter to the schedule. Better yet, is there a way to get how much time has elapsed since the start of the schedule.
Schedule.exponential<SomeResult>(someConfigDelay)
.jittered()
.whileOutput { it < someConfigMaxDelay }
.logOutput { log.debug("Current delay: $it - ${it.inWholeNanoseconds} ns") }simon.vergauwen
04/28/2022, 7:03 AMSchedule API!
The reason this isn't behaving as you expected is that the Duration output of Schedule.exponential is not updated by jittered.
jittered only updates the underlying delayTime, but not the Output of Schedule.exponential because it is not aware of what type of the previous output is.
You can easily write a custom Schedule to achieve this though.
@OptIn(ExperimentalTime::class)
fun <A> custom(
base: Duration,
factor: Double = 2.0,
jitter: Random = Random.Default
): Schedule<A, Duration> =
Schedule.delayed(Schedule.forever<A>()
.map { n ->
(base * factor.pow(n)) * jitter.nextDouble(0.0, 1.0)
})simon.vergauwen
04/28/2022, 7:04 AMSchedule.exponential and Schedule#jittered into a single Schedule so the output becomes the jittered delay.
I hope that helps 🙂Jonathan De Leon
04/28/2022, 7:21 PMJonathan De Leon
04/28/2022, 7:27 PMSchedule to create a policy that polls but with a timeout if no response.
Example - Let's continuously repeat a service call, as long as the call returns data, let's continue. Otherwise, if there is no data (using some predicate) and some time has elasped, let's end the repeat.
Thinking of using Schedule in some sort of webhook event streaming environment but we close the connection if after some time there has been no data.simon.vergauwen
04/29/2022, 8:31 AMwhileInput to validate the returned data with a custom predicate. It support suspension so you can even call other services or persistence to check if you need to continue, like health check endpoints or something.
A timeout I would encode it inside repeat itself since it all composes nicely. Taking the custom Schedule from above.
suspend fun networkCall(): Input {
delay(100.milliseconds)
return Input
}
object Input {
suspend fun isValid(): Boolean = true
}
custom<Input?>(1.seconds)
.whileInput { input: Input? - > input?.isValid() ?: false }
.repeat {
withTimeoutOrNull(500.milliseconds) {
networkCall()
}
}