在我的Shiny应用中,用户可以生成重型powerpoint报告。如果它包含很多幻灯片,则可以采用> 30分钟即可完成。因此,我想在独立的流程/任务中处理这些任务,即使应用程序关闭也可以工作 - 例如用户单击按钮生成报告,关闭应用程序,当报告准备好时,应用程序通过电子邮件通知用户。 是否有任何良好做法或经过验证的解决方案?
我的第一个想法是使用future
包并设置plan(multisession)
- 但我不确定当用户关闭应用时会发生什么 - future
会话也会关闭?
答案 0 :(得分:9)
本周我很幸运能够参加伦敦EARL,我认为我在那里看到的最好的演讲之一就是(Joe Cheng)。您需要promises包来实现这一点,并且正如文档中所述,它支持异步编程的特殊版本的闪亮devtools::install_github("rstudio/shiny@async")
。
使用dplyr
和promises
(future
也兼容),您可以找到关于其工作原理的第一份文档here。
作为一个小例子(取自文档),使用以下方法运行密集计算:
read.csv.async("data.csv") %...>%
filter(state == "NY") %...>%
arrange(median_income) %...>%
head(10) %...>%
View()
实际上会将控制台光标返回,允许您运行所需的任何其他命令,并在完成后自动打开View
选项卡。我可能会稍微挖掘出一个闪亮的例子,但请记住,这仍然在开发中,并将在今年年底之前发布(我会想到更全面的文档)。
答案 1 :(得分:1)
所以我使用future
包做了一些示例解决方法。即使应用程序关闭,代码也会在单独的会话(群集)中执行。我认为下一步就是弄清楚app应该如何检查进程是否仍在运行或已完成。有什么想法吗?
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)