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 pausingSchedule
Jö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