Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.25.20 breaks asynchronous tasks in reactive code blocks #176

Open
PGimenez opened this issue Feb 15, 2023 · 6 comments
Open

0.25.20 breaks asynchronous tasks in reactive code blocks #176

PGimenez opened this issue Feb 15, 2023 · 6 comments
Assignees
Labels
bug Something isn't working

Comments

@PGimenez
Copy link
Member

PGimenez commented Feb 15, 2023

I have this code that runs a @task in which a counter gets increased each second. It worked in 0.25.15, but after upgrading to 0.20.20 it stops working.

using GenieFramework
@genietools 

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

function ui()
        bignumber("Counter", :x)
end

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

this is the error I'm getting on 0.20.25 and Julia 1.8.5

┌ Error: 2023-02-15 20:56:50 Error attempting to invoke handler 3 for field Reactive{Bool}(Observable(true), 1, false, false, "") with value true
└ @ Stipple ~/.julia/packages/Stipple/Ird4L/src/stipple/mutators.jl:36
┌ Error: 2023-02-15 20:56:50 UndefVarError(:p)
└ @ Stipple ~/.julia/packages/Stipple/Ird4L/src/stipple/mutators.jl:37
@AbhimanyuAryan
Copy link
Member

I think @hhaensel can look at it. Can you check if it work on master with changes helmut made for kw. Not sure I understand the error

@PGimenez PGimenez changed the title 0.25.20 breaks asynchronous tasks in reactive code blocks 0.20.25 breaks asynchronous tasks in reactive code blocks Feb 16, 2023
@PGimenez PGimenez changed the title 0.20.25 breaks asynchronous tasks in reactive code blocks 0.25.20 breaks asynchronous tasks in reactive code blocks Feb 16, 2023
@hhaensel
Copy link
Member

hhaensel commented Feb 16, 2023

I know what happened. You are using a local variable in handlers which I had not thought of when I generalised the Reactive API.
I shall address this in a future release.
Meanwhile an easy work around is to define a private field instead of a local variable:

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

Note, that I have used @appinstead of @handlers which clears the variable cache, so that you can rename variables without having old names trailing in the model.

@hhaensel
Copy link
Member

I also enhanced @handlers so that you can also declare non_reactive fields:

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

@essenciary
Copy link
Member

essenciary commented Feb 16, 2023

Should the official recommendation (and demos) be to always use @app instead of @handlers? Or why don't we replace @app with @handlers at code level so all codebases get automatically migrated to the @app features?

@hhaensel
Copy link
Member

I explained in detail in #159.

In my eyes @app is the new standard, it combines both field and handler definition and clears both storages before setting the new values.
If you are adapting old code the quickest way is to replace the old @reactive statement with the respective @vars statement and to define handlers separately by @handlers, which then does not clear the REACTIVE_STORAGE, e.g. from

@reactive! mutable struct TreeDemo <: ReactiveModel
    d::R{Dict{String, Any}} = deepcopy(testdict)
    tree::R{Vector{Dict{Symbol, Any}}} = [dict_tree(testdict)]

    tree_selected::R{String} = ""
    tree_ticked::R{Vector{String}} = String[]
    tree_expanded::R{Vector{String}} = String[]
end

function handlers(model)
    on(model.isready) do isready
        isready && push!(model)
    end

    model
end

to

@appname TreeDemo

@vars begin
    d = deepcopy(testdict)
    tree = [dict_tree(testdict)]

    tree_selected = ""
    tree_ticked = String[]
    tree_expanded = String[]
end

@handlers
    onchange isready begin
        isready && @push
    end
end

@PGimenez
Copy link
Member Author

@hhaensel did you make any change about this? Are variables non-reactive by default now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants