Асинхронный процесс, блокирующий приложение R Shiny - PullRequest
0 голосов
/ 04 мая 2018

Должна быть возможность использовать пакеты R future и promises для запуска асинхронной (длительной) обработки через приложения Shiny без остановки остальной части приложения, пока асинхронный процесс выполняется в другом процессе R.

См .:

https://cran.r-project.org/web/packages/promises/vignettes/intro.html
https://cran.r-project.org/web/packages/promises/vignettes/overview.html
https://cran.r-project.org/web/packages/promises/vignettes/futures.html
https://cran.r-project.org/web/packages/promises/vignettes/shiny.html

Я заставил это работать в среде на основе R-скриптов, но не могу заставить это работать, когда я реализую простое блестящее приложение с 2 функциями. Функция «not-async» всегда блокируется во время работы асинхронной функции, но это не должно иметь место.

Я разместил тот же вопрос в репозитории GitHub пакета promises: https://github.com/rstudio/promises/issues/23

Я также публикую это здесь, надеясь, что кто-то может помочь.

Вопрос:

  1. Можете ли вы взглянуть на блестящий пример приложения, размещенный ниже, и сообщить мне, почему асинхронная обработка блокирует приложение? (Не должно блокировать).
  2. В идеале, можете ли вы предоставить небольшой пример приложения с неблокирующей асинхронностью и нормальной функциональностью (доступной во время выполнения асинхронизации)?

Окружающая среда

Mac OS 10.12

$ R --version
R version 3.4.3 (2017-11-30) -- "Kite-Eating Tree"

remove.packages("future")
remove.packages("promises")
remove.packages("shiny")

install.packages("future")
install.packages("devtools")
devtools::install_github("rstudio/promises")
devtools::install_github("rstudio/shiny")

> packageVersion("future")
[1] ‘1.8.1’
> packageVersion("promises")
[1] ‘1.0.1’
> packageVersion("shiny")
[1] ‘1.0.5.9000’

Односторонний вопрос о версии блестящего пакета, https://rstudio.github.io/promises/articles/intro.html говорит, что это должно быть> = 1.1, но даже при установке с помощью devtools версия остается 1.0.5 .... Это проблема или в документе есть опечатка?

Во-первых, вы можете использовать обещания с блестящими выходами. Если вы используете асинхронно-совместимую версию Shiny (версия> = 1.1), все встроенные функции renderXXX могут работать как с обычными значениями, так и с обещаниями.

Пример выпуска

Я реализовал это простое блестящее приложение, вдохновленное примером по URL-адресам, упомянутым выше. У блестящего приложения есть 2 "секции":

  1. Кнопка для запуска «длительной» асинхронной обработки. Это моделируется функцией read_csv_async, которая спит несколько секунд, считывает CSV-файл в кадр данных. Затем df отображается под кнопкой.
  2. Простая функциональность, которая должна работать в любое время (в том числе, когда была запущена асинхронная обработка): она включает ползунок, определяющий количество случайных значений, которые должны быть сгенерированы. Затем мы отображаем гистограмму этих значений.

Проблема в том, что вторая функция (обновление графика гистограммы) блокируется во время асинхронной обработки.

* * Global.R тысяча сорок-девять
library("shiny")
library("promises")
library("dplyr")
library("future")

# path containing all files, including ui.R and server.R
setwd("/path/to/my/shiny/app/dir")   

plan(multiprocess)

# A function to simulate a long running process
read_csv_async = function(sleep, path){
      log_path = "./mylog.log"
      pid = Sys.getpid()
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process started"), file = log_path, append = TRUE)
      Sys.sleep(sleep)
      df = read.csv(path)
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process work completed\n"), file = log_path, append = TRUE)
      df
}

ui.R

fluidPage(
  actionButton(inputId = "submit_and_retrieve", label = "Submit short async analysis"),
  br(),
  br(),
  tableOutput("user_content"),

  br(),
  br(),
  br(),
  hr(),

  sliderInput(inputId = "hist_slider_val",
              label = "Histogram slider",
              value = 25, 
              min = 1,
              max = 100),

  plotOutput("userHist")
)

server.R

function(input, output){
    # When button is clicked
    # load csv asynchronously and render table
    data_promise = eventReactive(input$submit_and_retrieve, {
        future({ read_csv_async(10, "./data.csv") }) 
    })
   output$user_content <- renderTable({
     data_promise() %...>% head(5)
    })


  # Render a new histogram 
  # every time the slider is moved
  output$userHist = renderPlot({
    hist(rnorm(input$hist_slider_val))
  })
}

data.csv

Column1,Column2
foo,2
bar,5
baz,0

Спасибо!

1 Ответ

0 голосов
/ 04 мая 2018

Так что это нормальное поведение, см. Ответ разработчика пакета на https://github.com/rstudio/promises/issues/23

Резюме:

В блестящих приложениях один процесс R может совместно использоваться несколькими пользователями. Если один пользователь отправляет долгосрочную задачу, то все другие пользователи, совместно использующие один и тот же базовый процесс R., блокируются. Цель promises - избежать этого. Таким образом, promises предотвратит блокировку между «пользовательскими сессиями» внутри одного процесса R, но не внутри одного «пользовательского сеанса».

Автор пакета отметил, что эта функция пока не поддерживается и что она может быть добавлена, если об этом попросит достаточное количество людей. Если вы ищете это, перейдите к выпуску GitHub, и вам понравился оригинальный вопрос - так измеряется интерес к новым функциям.

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...