2017-09-17 35 views
6

W mojej Shiny app użytkownicy mogą generować ciężki raport Powerpoint. Jeśli zawiera wiele slajdów, może to potrwać> 30 minut. Dlatego chciałbym przetworzyć te zadania w niezależnych procesach/zadaniach, które mogą działać nawet po zamknięciu aplikacji - np. przycisk kliknięcia użytkownika, aby wygenerować raport, zamyka aplikację, a kiedy raport jest gotowy aplikacja informuje użytkownika przez e-mail. Czy są jakieś dobre praktyki lub sprawdzone rozwiązania, aby to zrobić?R Błyskawiczne uruchamianie zadania/skryptu w innym procesie

Moja pierwsza myśl używał future pakiet z plan(multisession) zbioru - ale nie jestem pewien, co się dzieje, gdy użytkownik zamyka aplikację - future sesja zamyka też, czy nie?

+0

Czy 'mcparallel' działa dla ciebie? https://stat.ethz.ch/R-manual/R-devel/library/parallel/html/mcparallel.html –

+0

@Roman Luštrik, tak, ale czy 'mcparallel' pozwól mi stworzyć niezależną sesję, która działa nawet po zamknięciu aplikacja? – Taz

+0

Nie mam dostępu do komputera unix, więc nie mogę go przetestować. –

Odpowiedz

8

Miałem szczęście być w tym tygodniu w London EARL i uważam, że jedna z najlepszych prezentacji, jakie tam widziałem, dotyczy właśnie tego (Joe Cheng). Aby to działało, potrzebny jest pakiet promises, a także, jak mówi się w dokumentacji, specjalna wersja błyszczącego devtools::install_github("rstudio/[email protected]"), która obsługuje programowanie asynchroniczne.

Możesz znaleźć pierwszą dokumentację, here, w jaki sposób to działa, używając dplyr i promises (future jest również kompatybilny).

Jako mały przykład (wzięte z dokumentacji), prowadzenie intensywnych obliczeń przy użyciu następujących:

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

byłoby w istocie powrót kursora konsoli z powrotem, co pozwala uruchomić dowolną inną komendę chcesz i będzie automatycznie otwórz zakładkę View po jej zakończeniu. Być może uda mi się wydobyć nieco lśniący przykład, ale pamiętaj, że to wciąż jest w fazie rozwoju i zostanie wydane przed końcem roku (z bardziej wszechstronną dokumentacją, jaką sobie wyobrażam).

+2

Autor przyszłości tutaj; Potwierdzam, co Joe nad tym wszystkim rozwiąże. (Część, w której OP chce zamknąć aplikację i wrócić do niej później jest trudniejsza, mam wsparcie dla trwałych serializowalnych i przeładowywanych kontraktów futures na mojej liście rzeczy do zrobienia, ale to zajmie trochę czasu) – HenrikB

0

Tak, więc zrobiłem przykład obejścia przy użyciu pakietu future. Kod jest wykonywany w oddzielnej sesji (klastrze) nawet po zamknięciu aplikacji. Myślę, że następnym krokiem jest ustalenie, w jaki sposób aplikacja powinna sprawdzać, czy proces wciąż trwa, czy też jest gotowy. Jakieś pomysły?

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) 
Powiązane problemy