R блестящий запуск задачи / скрипта в другом процессе
В моем приложении Shiny пользователи могут генерировать тяжелые отчеты PowerPoint. Когда он содержит много слайдов, это может занять более 30 минут. И поэтому я хотел бы обрабатывать эти задачи в независимых процессах / задачах, которые могли бы работать, даже когда приложение закрыто - например, пользователь нажимает кнопку, чтобы сгенерировать отчет, закрывает приложение и когда отчет готов, приложение информирует пользователя по электронной почте. Есть ли хорошие практики или проверенные решения для этого?
Моей первой мыслью было использование future
пакет с plan(multisession)
установлен - но я не уверен, что происходит, когда пользователь закрывает приложение - future
сессия тоже закрывается или нет?
2 ответа
Мне посчастливилось побывать в Лондоне на этой неделе, и я думаю, что одна из лучших презентаций, которые я там увидел, была именно об этом (Джо Ченг). Для этого вам понадобится пакет обещаний, и, как сказано в документации, специальная версия блестящего devtools::install_github("rstudio/shiny@async")
который поддерживает асинхронное программирование.
Вы можете найти первую документацию здесь о том, как это работает, используя dplyr
а также promises
(future
также совместимо).
В качестве небольшого примера (взятого из документации) проведем интенсивный расчет с использованием следующего:
read.csv.async("data.csv") %...>%
filter(state == "NY") %...>%
arrange(median_income) %...>%
head(10) %...>%
View()
по существу вернет консольный курсор назад, что позволит вам запустить любую другую команду, и вы автоматически откроете View
вкладка, как только это было закончено. Возможно, мне удастся немного разглядеть блестящий пример, но имейте в виду, что он все еще находится в стадии разработки и будет выпущен до конца года (с более полной документацией, которую я мог бы представить).
Таким образом, я сделал несколько примеров, используя 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)