Update computation flag status

I'd like to update a computation status flag.

Basically this flag should have 4 states {NULL when starting the app, "running" when pushing START button, "queue" when waiting the end of the previous computation, "done" when the computation is done}.

I've made a few lines of code to illustrate the behaviour but of course it does not work as expected. :sweat_smile:

library(shiny)

ui <- shinyUI(fluidPage(
  titlePanel("Test update computation status flag"),
  sidebarLayout(
    sidebarPanel(
      fluidRow(
        column(8,
               "Status:",
               textOutput("status1")
        ),
        column(4,
               "Box1"
        )
      ),
      hr(),
      fluidRow(
        column(8,
               "Status:",
               textOutput("status2")
        ),
        column(4,
               "Box2"
        )
      ),
      hr(),
      fluidRow(align = "center",
               actionButton("startButton", "START")
      )
    ),
    mainPanel()
  )
))

server <- shinyServer(function(input, output, session) {
  cal1 <- reactiveVal(NULL)
  cal2 <- reactiveVal(NULL)
  stat1 <- reactiveVal(NULL)
  stat2 <- reactiveVal(NULL)
  observeEvent(input$startButton, {
    stat1("running")
    stat2("queue")
    Sys.sleep(2)
    cal1(1)
  })
  observeEvent(!is.null(cal1()), {
    stat1("done")
    stat2("running")
    Sys.sleep(2)
    cal2(2)
  })
  observeEvent(!is.null(cal2()), {
    stat2("done")
  })
  output$status1 <- renderText(stat1())
})

shinyApp(ui = ui, server = server)

image

Thanks for any help

Hi @olivier6088, if you have long running computations, you may want to leverage shiny's new asynchronous programming support which allows you to perform these expensive computations in a background process, and thus, free up your main shiny-server R process to do other things while those expensive computation(s) run. In this context, your queue notification may no longer relevant/informative, since you could use this infrastructure to instantly spin-off multiple jobs.

Getting started with async is difficult, but it may be worth your trouble

A relevant challenge that async introduces is communication between the background thread(s) and the main R shiny-server process, which is needed if you need to do something like update a progress bar for the computation running in the background thread. The ipc package process some nice tools for this, though:

https://cran.r-project.org/web/packages/ipc/vignettes/shinymp.html

1 Like

Hi @cpsievert, I was thinking about asynchronous programming and you gave me confirmation. Thank you.

Here is a code solution:

library(shiny)
library(ipc)
library(future)
plan(multiprocess)

calc <- function(i) {
  Sys.sleep(i * 2)
}

ui <- shinyUI(fluidPage(
  titlePanel("Test update computation status flag"),
  sidebarLayout(
    sidebarPanel(
      fluidRow(
        column(8,
               "Status:",
               textOutput("status1")
        ),
        column(4,
               "Box1"
        )
      ),
      hr(),
      fluidRow(
        column(8,
               "Status:",
               textOutput("status2")
        ),
        column(4,
               "Box2"
        )
      ),
      hr(),
      fluidRow(align = "center",
               actionButton("startButton", "START")
      )
    ),
    mainPanel()
  )
))

server <- shinyServer(function(input, output, session) {
  
  queue <- shinyQueue()
  queue$consumer$start(100) # Execute signals every 100 milliseconds
  
  stat1 <- reactiveVal(NULL)
  stat2 <- reactiveVal(NULL)
  
  observeEvent(input$startButton, {
    future({
      for(i in 1:2) {
        queue$producer$fireAssignReactive(paste0("stat",i), "queue")
      }
      for(i in 1:2) {
        queue$producer$fireAssignReactive(paste0("stat",i), "running")
        calc(i)
        queue$producer$fireAssignReactive(paste0("stat",i), "done")
      }
    })
    #Return something other than the future so we don't block the UI
    NULL
  })
  output$status1 <- renderText(stat1())
  output$status2 <- renderText(stat2())
})

shinyApp(ui = ui, server = server)
2 Likes

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.