delosh653 / mwshiny

An R package that extends Shiny apps over multiple connected windows.
Other
25 stars 3 forks source link

serv_calc() functions created for each window #2

Open delosh653 opened 4 years ago

delosh653 commented 4 years ago

With the new update (mwshiny 2.1.0), serv_calc() functions are being executed for each window opened. What that means is that if, for example, you have an observe-type function as one of your serv-calc() functions, you end up with as many observers as windows, which all do the same thing.

This is illustrated in the following example:

library(mwshiny)

ui_win <- list()

ui_win[["Controller"]] <- fluidPage(
  actionButton(inputId = "go",
               label = "Build!")
)

# then we add what we want to see in the scatter section
ui_win[["Scatter"]] <- fluidPage(
  titlePanel("Scatter")
)

serv_calc <- list()

count <- 0

serv_calc[[1]] <- function(calc, sess){
  # this is going to activate any time I press "build!"
  observeEvent(calc$go, {
    count <<- count+1
    print(paste0("count: ", count))
  })
}

serv_out <- list()

#run!
mwsApp(ui_win, serv_calc, serv_out)

If you press the "Build!" button on the controller window, with all the initial windows open (WindowSelector, Controller, Scatter), the output is not count: 1, as should be, but:

count: 1
count: 2
count: 3

Ideally, all serv_calc() functions should be shared between windows, such that there is only one instance at once, rather than the amount of windows.

A couple ideas on how to fix it (though, I don't know if any are possible):

  1. Change the architecture such that one server is connected to several UIs (several windows)
  2. Have a headless "dummy" window running in the background that handles all calculations, so that all the UIs only have servers that update input/output

Any fixes/suggestions are very appreciated!

delosh653 commented 4 years ago

I'm going to push a small bug fix update that sort of fixes this, but in order for it to work, you have to keep the first rendered WindowSelector window open for the duration of app use. Definitely is not a permanent solution, and will not be put on CRAN.

olyerickson commented 4 months ago

@delosh653 We can definitely confirm this behavior.

We discovered this github issue while tracking down a problem we're having with multiple marker events firing when interacting with Leaflet. In our mwshiny application, normal Leaflet marker interactions (single-click-only or double-click-only) work fine, but we are also introducing special marker behavior where the number of clicks makes a difference, and chaos is ensuing --- but only when we implement our marker event handlers within the serv_calc universe. If we step outside of mwshiny and manage those as "normal" Shiny reactives, things seem to behave.

olyerickson commented 4 months ago

@delosh653 I re-implemented your test using a structure with count as a reactive, and with count appearing in the output page:

library(mwshiny)

ui_win <- list()

ui_win[["Controller"]] <- fluidPage(
  actionButton(inputId = "go",
               label = "Build!")
)

# then we add what we want to see in the scatter section
ui_win[["Scatter"]] <- fluidPage(
  titlePanel("Scatter"),
  textOutput("scatter_count")
)

serv_calc <- list()

serv_calc[[1]] <- function(calc, sess){
  calc$count <- 0
}

serv_calc[[2]] <- function(calc, sess){
  # this is going to activate any time I press "build!"
  observeEvent(calc$go, {
    calc$count <- calc$count+1
    print(paste0("count: ", calc$count))
  })
}

serv_out <- list()

serv_out[["scatter_count"]] <- function(calc, sess){
  renderText({
    paste0("count: ", calc$count)
  })
}
#run!
mwsApp(ui_win, serv_calc, serv_out)