Stipple.jl icon indicating copy to clipboard operation
Stipple.jl copied to clipboard

Calling @onchange while a @task is running causes "Failed to store session data" error

Open PGimenez opened this issue 2 years ago • 1 comments
trafficstars

I have a variable total that each second is increased by an amount x taken from a text field in the UI. This is done asynchronously with a @task so that the program can listen to @onchange events.

using GenieFramework
@genietools 

@handlers begin
    p = @task 1+1
    total = 0
    @in x = 0.00
    @onchange x begin
        if !istaskstarted(p) || istaskdone(p) 
            p = @task begin
                println("Task started")
                while total <= 100
                    total = total + x
                    println(total)
                    sleep(1)
                end
            end
            schedule(p)
        end
    end
end

function ui()
    textfield("x value", :x)
end

@page("/", ui)
Server.isrunning() || Server.up()

It works, but when I change the value of x from 1 to 2 I get the following:

Task started
1.0
2.0
3.0
4.0  <---- Here I change x to 2
┌ Error: 2023-01-17 17:03:27 Failed to store session data
└ @ GenieSessionFileSession ~/.julia/packages/GenieSessionFileSession/otnJC/src/GenieSessionFileSession.jl:41
6.0┌ Error: 2023-01-17 17:03:27 ErrorException("cannot serialize a running Task")
└ @ GenieSessionFileSession ~/.julia/packages/GenieSessionFileSession/otnJC/src/GenieSessionFileSession.jl:42

┌ Error: 2023-01-17 17:03:27 Resetting session
└ @ GenieSessionFileSession ~/.julia/packages/GenieSessionFileSession/otnJC/src/GenieSessionFileSession.jl:46
8.0
10.0
12.0

I've also tried defining the task outside of the @onchange block, but in that case the counter does not increase.

@handlers begin
    p = @task 1+1
    total = 0
    @in x = 0.00
    p = @task begin
        println("Task started")
        while total <= 100
            total = total + x
            println(total)
            sleep(1)
        end
    end
    @onchange x begin
        if !istaskstarted(p) || istaskdone(p) 
            schedule(p)
        end
    end
end

What is the cause of this error? Can it be fixed somehow?

PGimenez avatar Jan 17 '23 16:01 PGimenez

For a little more context, here's what I'm trying to do. I want to have a differential equation simulation running in the background, and control the eq's parameters in the UI. The simulation is run by calling a solver function in a loop over time. Whenever a parameter is changed, the diff eq should be instantly updated and the simulation proceed with the new parameters.

In the code below, the step! function in the while loop calculates the eq solution at t+t_step. The value of t_step can be set from the UI. This works well, only I'm getting the error in the previous post.

using GenieFramework
using DifferentialEquations, ModelingToolkit
@genietools 

function define_ODE()
    @parameters t σ ρ β
    @variables x(t) y(t) z(t)
    D = Differential(t)

    eqs = [D(x) ~ σ * (y - x),
           D(y) ~ x * (ρ - z) - y,
           D(z) ~ x * y - β * z]
    @named sys = ODESystem(eqs)
    sys = structural_simplify(sys)
    u0 = [x => 1.0,
          y => 0.0,
          z => 0.0]
    p = [σ => 10.0,
         ρ => 28.0,
         β => 8 / 3]

    tspan = (0.0, 100.0)
    ODEProblem(sys, u0, tspan, p, jac = true)
end
    
prob = define_ODE()
integrator = DifferentialEquations.init(prob, Tsit5())
t_end=100

@handlers begin
    p = @task 1+1
    schedule(p)
    prob = define_ODE()
    @in t_step = 0.00
    @onchange t_step begin
        println(t_step)
        if p._state == 1
            p = @task begin
                @show p._state
                while integrator.sol.t[end] <= t_end
                    sleep(1)
                    println(integrator.sol.t[end],' ', t_step, ' ', p._state)
                    step!(integrator, t_step)
                end
                DifferentialEquations.reinit!(integrator)
            end
            schedule(p)
        end
    end
end

function ui()
    textfield("Time step", :t_step)
end

@page("/", ui)
Server.isrunning() || Server.up()

PGimenez avatar Jan 18 '23 11:01 PGimenez