8

在我的 Shiny 应用程序中,用户可以生成大量的 powerpoint 报告。当它包含大量幻灯片时,可能需要超过 30 分钟才能完成。因此,我想在独立的进程/任务中处理这些任务,这些任务即使在应用程序关闭时也可以工作 - 例如,用户单击按钮生成报告,关闭应用程序,当报告准备好时,应用程序通过电子邮件通知用户。是否有任何好的做法或经过验证的解决方案可以做到这一点?

我的第一个想法是使用future带有plan(multisession)set 的包 - 但我不确定当用户关闭应用程序时会发生什么 -future会话是否也关闭?

4

2 回答 2

10

我很幸运这周来到了伦敦 EARL,我认为我在那里看到的最好的演讲之一就是关于这个(由 Joe Cheng)。您将需要promises包才能使其工作,并且正如文档中所说devtools::install_github("rstudio/shiny@async"),支持异步编程的特殊版本的闪亮。

您可以在此处dplyr找到有关使用and promises(future也是兼容的)如何工作的第一个文档。

作为一个小例子(取自文档),使用以下内容运行密集计算:

read.csv.async("data.csv") %...>%
  filter(state == "NY") %...>%
  arrange(median_income) %...>%
  head(10) %...>%
  View()

基本上会返回控制台光标,允许您运行任何其他您想要的命令,并View在完成后自动打开选项卡。稍等片刻,我可能会找到一个闪亮的例子,但请记住,这仍在开发中,将在今年年底之前发布(我想会有更全面的文档)。

于 2017-09-17T16:54:02.427 回答
1

所以我使用future包做了一些示例解决方法。即使应用程序关闭,代码也会在单独的会话(集群)中执行。我认为下一步只是弄清楚应用程序应该如何检查进程是否仍在运行或已完成。有任何想法吗?

library(future)
cl <- parallel::makeCluster(2L)
plan(cluster, workers = cl)

server <- function(input, output) {
  observeEvent(input$run, {

    iteration <- as.numeric(input$iteration)
    path <- input$path

    future::future({
      writeLog <- function(n, path) {
        file.remove(path)
        for (i in 1:n) {
          cat("#", i, "-",  as.character(Sys.time()), "\n", file = path, append = TRUE)
          Sys.sleep(1)
        }
      }
      writeLog(iteration, path)
    }, globals = c("iteration", "path"))
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      tags$div("This app writes to file in cluster which means it is computed in parallel to this session. 
               It will execute even when app is closed.")
      , br()
      , shiny::textInput("path", "Path to log file", value = "/src/dev/export_performance/future.log")
      , shiny::textInput("iteration", "Iteration number", value = 60)    
    ),
    mainPanel(
      br()
      , actionButton("run", "Run future")
    )
  )
)

shinyApp(ui = ui, server = server)
于 2017-09-17T18:44:12.833 回答