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

httpuv::service does not seem to be working #148

Closed
harveyl888 opened this issue Jun 5, 2018 · 7 comments
Closed

httpuv::service does not seem to be working #148

harveyl888 opened this issue Jun 5, 2018 · 7 comments

Comments

@harveyl888
Copy link

I'm having some issues using httpuv::service as a way to monitor progress and interrupt execution of a shiny app using a button. It's worked in the past but now does not seem to be working, possibly due to an upgrade in shiny or httpuv.

By way of example I've found that the code at https://stackoverflow.com/questions/30587883/is-it-possible-to-stop-executing-of-r-code-inside-shiny-without-stopping-the-sh/34517844#34517844 works under some installations but not others. The app should be interrupted when the stop button is pressed.

The code works on an old server running shiny 0.12.2.9006 and httpuv 1.3.3
The code does not work under shiny 1.1.0 and httpuv 1.4.3

library(shiny)
analyze <- function(session=shiny::getDefaultReactiveDomain()){
  continue = TRUE
  lapply(1:100, function(x) {
    if(continue){
      print(x)
      Sys.sleep(1)
      # reload inputs
      httpuv:::service()
      continue <<- !isTRUE(session$input$stopThis)
    }
  }
  )
}

shinyApp(
  ui = fluidPage(
    actionButton("start","Start",class="btn-primary", onclick="Shiny.onInputChange('stopThis',false)"),
    actionButton("stop","Stop",class="btn-danger", onclick="Shiny.onInputChange('stopThis',true)")
  ),
  server = function(input, output, session) {
    observeEvent(input$start, {
      analyze()
    })
  }
)
@wch
Copy link
Collaborator

wch commented Jun 6, 2018

That's definitely not how service() is meant to be used -- runApp() indirectly calls service(), and it in turn makes all the machinery in Shiny run. The effect of your code is to recursively call service(), which is not how it's supposed to work.

That said, this is an interesting use case, and I think we can come up with a way to do what you're looking for using Shiny's new async features. Stay tuned...

@harveyl888
Copy link
Author

Thanks Winston. Shame - it was really useful to be able to monitor a reactive variable during a long process and then pause or break as appropriate.
Would be interested if there's a solution using async programming.

@jcheng5
Copy link
Member

jcheng5 commented Jun 7, 2018

@harveyl888 I have a number of ways to solve this that we can talk about. It'd be helpful to know from you:

  1. Are the tasks in question like the example you posted, in that, you're doing homogeneous operations on a list of data? Or was that just an example, and actually you've got a sequence of heterogeneous steps that you want to be able to interrupt in between them?
  2. Would it be desirable to execute these operations outside of the main R process? Or do you want it to stay in-process for some reason?

@harveyl888
Copy link
Author

Hi Joe. Thanks in advance.

  1. The example above covers pretty much what I'm aiming to do. It's a series of operations within a loop. I'd like to break the loop upon a button-press but not exit the app.
  2. I don't see why the operations couldn't run in outside the main R process. They currently reside in a module and depend on some additional functions. When interrupted a reactiveValue is changed. Would processes be able to share reactiveValues?
    Hope this helps. I can put together an MWE but the example above is quite close to the code I have, except for the use of a global variable.

@jcheng5
Copy link
Member

jcheng5 commented Jun 8, 2018

Here's a start:

https://gist.github.com/jcheng5/1ff1efbc539542ecedde92f25458a872

We should be able to do much better than this (for example, automatically stopping if the Shiny session that started the task stops; and working with async) but hopefully this can get you unblocked for now.

@harveyl888
Copy link
Author

Thanks @jcheng5. I've taken the gist and found that you can run with reactiveValues if func is wrapped in isolate. This is a great help and will certainly set me down the right path. Thanks again for all the help!

@jcheng5
Copy link
Member

jcheng5 commented Jun 13, 2018

@harveyl888 Ah, I forgot to answer the reactiveValues part of your question. When running in the same process, you can totally do that, but keep in mind those values may change under you as the user continues to use the application. If you want to "snapshot" the reactiveValues at the start time of the operation, you can do that by reading the reactiveValues you want (with isolate) into temp variables. When running in a different process, the values won't change under you, but you may end up copying more data into the background process then you actually need to; again, the solution is to copy the values you want (with isolate) into temp variables, and those will be the only ones copied to the background process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants