Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny - Continuous background task

I would like to know if it is possible to keep a continuous background task while running a Shiny app. This means, for instance, that a "thread" could be downloading data from a web page to a database while shinyApp is running.

Even more, could it be possible to interact with the data from the external background "thread"? (e.g. while it is being download, make a plot or something).

In the video tutorial, it is said that: "Code outside the server function will be run once per R session (worker)". So, the code I need I think should be placed outside the server function.

Is it possible to achieve the scene I describe? Or do I need another external R instance (outside the shinyApp scripts)?

Thanks in advance.

like image 734
aloplop85 Avatar asked Jul 21 '15 21:07

aloplop85


1 Answers

I was thinking about this, and I think it is possible, but the implementation I have in mind is platform-specific. In this case, I will assume ubuntu 14.04.

Lets say you have some computationally intensive task:

ui.R:

library(shiny)
fluidPage(
  numericInput('number','Number',10000000),
  textOutput('CalcOutput')
)

server.R

library(shiny)
function(input,output,session) {
   output$CalcOutput <- renderText({
    sort(runif(input$number))
   })
}

migrate the operation to a function of the relevant variables in a subfile:

newfile.R

saveRDS(sort(runif(commandArgs(TRUE)[1])), file = 'LargeComputationOutput')

change your server.R

function(input, output) {
  observe({
    # Starts script as a background process, but completes instantaneously
    system(paste('Rscript newfile.R',input$number,'&')) 
  })

  CalculationOutput <- reactive({
    invalidateLater(5000)
    validate(
      need(file.exists('LargeComputationOutput'),'Calculation In Progress'),
      need(file.info('LargeComputationOutput')$mtime > Sys.time()-5,'Calculation In Progress')
    )
    x <- readRDS('LargeComputationOutput')
  })

  output$CalcOutput <- renderText({
    CalculationOutput()[300]
  })


}

This is still a little buggy, but it's proof of concept, that you can move intensive operations to sub-rprocesses, and have a reactive listener detect when those calculations are done.

EDIT: Shiny will also need permissions to write to the relevant location.

like image 142
Shape Avatar answered Oct 20 '22 03:10

Shape