R Shiny在不同进程中运行任务/脚本

8
在我的 Shiny 应用中,用户可以生成大量幻灯片的报告。当幻灯片数量较多时,可能需要超过30分钟才能完成。因此,我希望在独立进程/任务中处理这些任务,即使应用程序关闭也可以工作 - 例如,用户单击按钮以生成报告,关闭应用程序,当报告准备好时,应用程序通过电子邮件通知用户。
有没有任何好的做法或经过验证的解决方案来实现这一点?
我的第一个想法是使用 future 包,并设置 plan(multisession) - 但我不确定当用户关闭应用程序时会发生什么 - future 会关闭吗?

mcparallel 对你有用吗?https://stat.ethz.ch/R-manual/R-devel/library/parallel/html/mcparallel.html - Roman Luštrik
@Roman Luštrik,是的,但是mcparallel能让我创建独立的会话,即使我关闭应用程序也可以工作吗? - Taz
我无法访问 Unix 机器,因此我无法真正测试它。 - Roman Luštrik
@Taz,您在 GitHub 上有吗?我正在尝试做类似的事情(让用户使用 Shiny 构建 PPT),这可能会对我有很大帮助。 - Richard Lusch
@Richard Lusch,我在客户应用程序中使用的是这个版本更加完善的东西:https://github.com/Tazovsky/shiny-async-demo + officer R 软件包。如果您需要任何细节,请给我发送电子邮件 ;) - Taz
2个回答

10

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

您可以在此处找到有关使用dplyrpromisesfuture也兼容)进行工作的第一份文档。

作为一个小例子(摘自文档),可以使用以下代码运行密集计算:

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

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


3
未来的作者在这里确认,Joe正在处理的问题将得到解决。对于用户想要关闭应用并稍后回到它的部分更加棘手;我在待办事项清单上支持持久化可序列化和可重新加载的未来任务,但需要一些时间来实现。 - HenrikB

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接