R shiny future: plan(multiprocess)/plan(multicore) + Kill long running process

ぐ巨炮叔叔 提交于 2019-12-22 05:24:13

问题


I am writing this to seek some help in using plan(multiprocess) or plan(multicore) and killing long running processes in my shiny app. The app has multiple future events (long running processes) that run on clicking their corresponding actionButton. Below is an example app of future() command used within the server function in the app. And i have been using stopMulticoreFuture(fut) to kill the processes.

library(shiny)
library(shinydashboard)
library(promises)
plan(multicore)
library(ipc)
sidebar <- dashboardSidebar(width = 200, sidebarMenu(id = "tabs",
                                                     menuItem("File", tabName = "tab1", icon = icon("fas fa-file"))))
body <- tabItem(tabName = "tab1",h2("Input File"),
                fluidRow(tabPanel(
                    "Upload file",
                    value = "upload_file",
                    fileInput(
                      inputId = "uploadFile",
                      label = "Upload Input file",
                      multiple = FALSE,
                      accept = c(".txt")
                    ),
                    checkboxInput('header', label = 'Header', TRUE)
                  ),
                  box(
                    title = "Filter X rows",
                    width = 7,
                    status = "info",
                    tabsetPanel(
                      id = "input_tab",
                      tabPanel(
                        "Parameters",
                        numericInput(
                          "nrows",
                          label = "Entire number of rows",
                          value = 5,
                          max = 10
                        ),
                        actionButton("run", "Analyze"),
                        actionButton("cancel", "Cancel")
                      ),
                      tabPanel(
                        "Results",
                        value = "results",
                        navbarPage(NULL,
                                   tabPanel(
                                     "Table", DT::dataTableOutput("res_table"), 
                                     icon = icon("table")
                                   )),
                        downloadButton("downList", "Download")
                      )
                    )
                  )
                ))
ui <-
  shinyUI(dashboardPage(
    dashboardHeader(title = "TestApp", titleWidth = 150),
    sidebar,dashboardBody(tabItems(body))
  ))


server <- function(input, output, session) {
  file_rows <- reactiveVal()
  observeEvent(input$run, {
    prog <- Progress$new(session)
    prog$set(message = "Analysis in progress",
             detail = "This may take a while...",
             value = NULL)
    file_nrows <- reactive({
      return(input$nrows)
    })

    file_nrows_value <- file_nrows()

    file_input <- reactive({
      return(input$uploadFile$datapath)
    })

    file_input_value <- file_input()

    fut<- NULL

    fut<<- future({system(paste(
      "cat",
      file_input_value,
      "|",
      paste0("head -", file_nrows_value) ,
      ">",
      "out.txt"
    ))
    head_rows <- read.delim("out.txt")
    head_rows
    }) %...>%
     file_rows() %>%
     finally(~prog$close())
})

  observeEvent(file_rows(), {
    updateTabsetPanel(session, "input_tab", "results")
    output$res_table <-
      DT::renderDataTable(DT::datatable(
        file_rows(),
        options = list(
          searching = TRUE,
          pageLength = 10,
          rownames(NULL),
          scrollX = T
        )
      ))
  })

  output$downList <- downloadHandler(
    filename = function() {
      paste0("output", ".txt")
    }, content = function(file) {
      write.table(file_rows(), file, row.names = FALSE)
    }
  )

  observeEvent(input$cancel,{
    stopMulticoreFuture(fut)
  })

}

shinyApp(ui = ui, server = server)

When i click "Cancel" button, the UI gets disabled but the console shows the below warning and the command still gets executed in the console.

Warning: Error in stopMulticoreFuture: stopMulticoreFuture only works on multicore futures

Since this example represents a quick running process the future() command gets executed before clicking Cancel.

In real case, even after clicking “Cancel” the command inside the future (long process) still runs in the console after the warning while the UI is already disabled.

The app is currently run on MAC with 4 cores. How could i kill the process running in the console rather just getting the UI disabled?

I am currently testing my app and would be great to have expert input in planning multiprocess/multicore and killing the processes to make the app efficient for running async processes among parallel users. The final app will be running on Ubuntu machine with 4 virtual CPUs.


回答1:


A couple problems here:

  1. You are missing library(promises), plan(multicore) and library(ipc).
  2. fut is not a future, it is a promise because of the %...>%, so stopMulticoreFuture won't work on it.
  3. The ObserveEvent expression needs to return something other than the promise, otherwise your UI will block.
  4. Since stopMulticoreFuture just kills the process, I can't assure you that it will work with system calls that create subprocesses. You may need to figure out the pid values for these and kill them yourself.


来源:https://stackoverflow.com/questions/53151431/r-shiny-future-planmultiprocess-planmulticore-kill-long-running-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!