Jörg Winter
11/20/2022, 9:07 AMrepeat (think AtomicBoolean or something similar). So the Schedule actually continues, but the effect to be run by repeat has to evaluate that switch inside it's own logic.
What I am looking for is something like an pause operator, which completely stops the Schedule until some condition gets true again.
Is this semantic possible with the current operators somehow or could that be added in the future ?simon.vergauwen
11/20/2022, 11:05 AMsimon.vergauwen
11/20/2022, 11:08 AMawait a CompletableDeferred.
Depending on when you need it to pause you can implement it differently. If you need to pause/resume multiple times it might be more tricky, but you can probably use a Channel(RENDEZ_VOUS) instead of a CompletableDeferred or both combined.Jörg Winter
11/20/2022, 11:10 AMsimon.vergauwen
11/20/2022, 11:11 AMJörg Winter
11/20/2022, 11:11 AMJörg Winter
11/20/2022, 11:12 AMsimon.vergauwen
11/20/2022, 11:13 AMval pauser = Channel<Unit>(Channel.RENDEZ_VOUS)
launch {
delay(10.seconds)
pauser.send(Unit)
}
Schedule.forever<Unit>().repeat {
println("Running")
pauser.receive()
}
pauser.receive() will wait until there is a value available through send(Unit), but send(Unit) will also suspend until receive takes it off the Channel.simon.vergauwen
11/20/2022, 11:14 AMfun Application.pauser(
channel: Channel<Unit>
): Route =
routing {
post("/pauser") {
launch { channel.send(Unit) }
call.respond(ACCEPTED)
}
}
Schedule.forever<Unit>().repeat {
println("Running")
pauser.receive()
}Jörg Winter
11/20/2022, 11:15 AMsimon.vergauwen
11/20/2022, 11:16 AMSchedule
Schedule.invoke({ Unit }) { _,_ ->
pauser.receive()
}simon.vergauwen
11/20/2022, 11:16 AMsimon.vergauwen
11/20/2022, 11:16 AMJörg Winter
11/20/2022, 11:19 AMsimon.vergauwen
11/20/2022, 11:19 AMChannel needs to use RENDEZ_VOUS strategy. That means that there needs to be an element trade-off, so like a Queue with capacity = 0.Jörg Winter
11/20/2022, 11:20 AMJörg Winter
11/20/2022, 11:21 AMJörg Winter
11/20/2022, 11:22 AMinvoke I guess 👍Jörg Winter
11/20/2022, 11:22 AMJörg Winter
11/20/2022, 11:24 AMJörg Winter
11/20/2022, 11:25 AMJörg Winter
11/20/2022, 11:55 AMval switch = AtomicBoolean(true)
@OptIn(ExperimentalTime::class)
fun repeater(): Schedule<Unit, Int> =
Schedule.spaced<Unit>(1.seconds).compose(Schedule.invoke({}) { input, state ->
if (switch.get())
Schedule.Decision.Companion.cont(1.seconds, input, Eval.Always {})
else
// What goes here ?
})
but I can't find 'What goes here ?'simon.vergauwen
11/20/2022, 12:09 PMJörg Winter
11/20/2022, 12:22 PMpauser.receive() from your snippet) outside, preferably in the Schedule composition.
I understand that you propose using invoke for that, but I do not understand the Schedule.Decision mechanism I guess.Jörg Winter
11/20/2022, 12:23 PMJörg Winter
11/20/2022, 12:24 PMsimon.vergauwen
11/20/2022, 12:24 PMval pauser = Channel<Boolean>(Channel.RENDEZ_VOUS)
fun Application.pauser(): Route =
routing {
post("/pauser") {
launch { channel.send(true) }
call.respond(ACCEPTED)
}
}
val pausingSchedule = Schedule.invoke({ Unit }) { _,_ ->
val shouldContinue = pauser.receive()
Decision(shouldContinue, 0.seconds, Unit, Eval.now(Unit))
}
val repeater: Schedule<Unit, Int> =
Schedule.spaced<Unit>(1.seconds) zipLeft pausingScheduleJörg Winter
11/20/2022, 12:26 PMJörg Winter
11/20/2022, 12:28 PMsimon.vergauwen
11/20/2022, 12:29 PMChannel<Unit> to Channel<Boolean>, but you could also add an AtomicBoolean somewhere. The boolean goes into the Decision. I updated the snippet, I think this will type-check now.Jörg Winter
11/20/2022, 1:15 PMsimon.vergauwen
11/20/2022, 1:15 PMJörg Winter
11/20/2022, 1:15 PMJörg Winter
11/20/2022, 1:16 PMJörg Winter
11/20/2022, 1:52 PMJörg Winter
11/21/2022, 6:16 PMJörg Winter
11/21/2022, 6:19 PM