diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index f5237014e2..783dc7a434 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -122,7 +122,7 @@ function run_reactive_core!( # Send intermediate updates to the clients at most 20 times / second during a reactive run. (The effective speed of a slider is still unbounded, because the last update is not throttled.) # flush_send_notebook_changes_throttled, - send_notebook_changes_throttled, flush_notebook_changes = throttled(1.0 / 20) do + send_notebook_changes_throttled, flush_notebook_changes = throttled(1.0 / 20; runtime_multiplier=2.0) do send_notebook_changes!(ClientRequest(; session, notebook)) end send_notebook_changes_throttled() diff --git a/src/evaluation/Throttled.jl b/src/evaluation/Throttled.jl index 07cb0141e2..71a96d9980 100644 --- a/src/evaluation/Throttled.jl +++ b/src/evaluation/Throttled.jl @@ -13,7 +13,7 @@ This throttle is 'leading' and has some other properties that are specifically d Inspired by FluxML See: https://github.com/FluxML/Flux.jl/blob/8afedcd6723112ff611555e350a8c84f4e1ad686/src/utils.jl#L662 """ -function throttled(f::Function, timeout::Real) +function throttled(f::Function, timeout::Real; runtime_multiplier::Float64=0.0) tlock = ReentrantLock() iscoolnow = Ref(false) run_later = Ref(false) @@ -29,7 +29,7 @@ function throttled(f::Function, timeout::Real) function schedule() # if the last runtime was quite long, increase the sleep period to match. - Timer(timeout + last_runtime[] * 2) do _t + Timer(timeout + last_runtime[] * runtime_multiplier) do _t if run_later[] flush() schedule() diff --git a/src/webserver/SessionActions.jl b/src/webserver/SessionActions.jl index d1066bc0c7..75f35d1702 100644 --- a/src/webserver/SessionActions.jl +++ b/src/webserver/SessionActions.jl @@ -186,7 +186,7 @@ function add(session::ServerSession, notebook::Notebook; run_async::Bool=true) end end - notebook.status_tree.update_listener_ref[] = first(throttled(1.0 / 5) do + notebook.status_tree.update_listener_ref[] = first(throttled(1.0 / 5; runtime_multiplier=2.0) do # TODO: this throttle should be trailing Pluto.send_notebook_changes!(Pluto.ClientRequest(; session, notebook)) end) diff --git a/test/Throttled.jl b/test/Throttled.jl index 48285ebe5f..17d0e604b6 100644 --- a/test/Throttled.jl +++ b/test/Throttled.jl @@ -1,4 +1,5 @@ import Pluto:throttled +using Pluto.WorkspaceManager: poll @testset "Throttled" begin x = Ref(0) @@ -19,9 +20,14 @@ import Pluto:throttled # we have an initial cooldown period in which f should not fire... # ...so x is still 1... @test x[] == 1 - sleep(2dt) + sleep(1.5dt) # ...but after a delay, the call should go through. @test x[] == 2 + + # Let's wait for the cooldown period to end + sleep(dt) + # nothing should have changed + @test x[] == 2 # sleep(0) ## ASYNC MAGIC :( @@ -81,4 +87,27 @@ import Pluto:throttled sleep(2dt) @test x[] == 13 + #### + + ft() + @test poll(2dt, dt/60) do + x[] == 14 + end + # immediately fire again, right after the last fire + ft() + ft() + # this should not do anything, because we are still in the cooldown period + @test x[] == 14 + # not even after a little while + sleep(0.1dt) + @test x[] == 14 + + # but eventually, our call should get queued + sleep(dt) + @test x[] == 15 + sleep(2dt) + + #### + + end \ No newline at end of file