Используйте параллельные процессы для использования вызовов API в будущем

#r #shiny #get #r-future

Вопрос:

Мое блестящее приложение отображает 10 различных фоволтаических систем. Для каждой фотоэлектрической системы приложение выполняет одни и те же вычисления. Я использую модули в shiny, чтобы уменьшить количество строк. Этот процесс похож на следование:

  1. Данные загружаются из API (модуля)
  2. Данные из api пересчитываются (Модуль)
  3. Данные графически обрабатываются с помощью инфобоксов, ggplot и т.д.

В настоящее время код выполняется, и время ожидания загрузки данных API очень велико. Я хочу сократить время ожидания конечного пользователя с помощью будущего пакета.

В настоящее время я не понимаю, как реализовать future() в моих блестящих модулях.

Например:

API api

   api(
    id = "bb55",
    df = read.csv("Anlagen/Barbarastrasse_55-1/bb55.csv"),
    api_siteid =  "8784240",
    api_key = "EY0HXOAH1Y6fgMY912RGGPUGJD5C2G",
    startmonth = "apr2029",
    startdate <- "20200401",
    url = "https://monitoringapi.solaredge.com/site/",
    db_location = "Anlagen/barbstreet_55-1/bb55.csv"
  )
bb55_act <- read.csv("Anlagen/Barbarastrasse_55-1/bb55.csv")
 

Сервер Модулей

 ib_prod_month_pkWp_UI  <- function(id){
  valueBoxOutput(NS(id,"ib_prod_pkwp_month"))
}

ib_prod_month_pkWp_server <- function(id,df, kwp_size){
  moduleServer(id, function(input, output, session){ 
    output$ib_prod_pkwp_month <- renderInfoBox({
      result <- df %>%
        mutate(timestamp = as.POSIXct(timestamp, format = "%Y-%m-%d %H:%M:%S")) %>%
        filter(year(timestamp) == year(Sys.Date()) amp;
                 month(timestamp) == month(Sys.Date())) %>%
        summarise(kwh = sum(prod) / as.numeric(kwp_size))
      valueBox(
        subtitle = "Prod. diesen Monat p. kWp",
        prettyNum(
          result$kwh,
          big.mark = ".",
          decimal.mark = "," ,
          digits = 4,
          scientific = FALSE
        )
      )
      
    })
  })
}

ib_prod_today_pkWp_server("bb55_1_ib_prod_pkwp_today", df = bb55_act, kwp_size = bb55_size)
 

Результатом api() является запись новых данных в файл csv. После этого csv-файл загружается в bb55_act = df.

Этот процесс повторяется для каждой фотоэлектрической системы. Я хотел бы распараллелить вызов API, потому что это наиболее трудоемкая часть кода.

Спасибо за вашу помощь!

Комментарии:

1. Имейте в виду, что вы показываете ключ API в своем коде!

2. Я изменил некоторые буквы в коде, это не настоящий код api

Ответ №1:

Насколько я могу судить, использование {future} будет влиять на производительность только в том случае, если несколько пользователей используют приложение одновременно. Поскольку вы сохраняете ответы API в локальной файловой системе, я бы предложил использовать callr::r_bg() их для запуска запросов API в фоновом задании и получения ответов с помощью shiny::reactiveFileReader() .

Смотрите следующий пример, где я сделал некоторые упрощения

 api_args <- list(
  list(id = "first_resource", destfile = "~/api_files/destfile1.csv"),
  list(id = "second_resource", destfile = "~/api_files/destfile2.csv")
)

make_api_calls <- function() {
  lapply(api_args, function(x) {
    callr::r_bg(api, x)
  })
}

mod_valuebox_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    df <- reactiveFileReader(api_args[[1]]$destfile)
    result <- df %>%
      summarise(kwh = sum(prod) / as.numeric(kwp_size))
    output$balueBox <- valueBox(result$kwh)
  })
}
 

Упрощения

  • Я предполагаю, что функция API имеет один аргумент, определяющий ресурс, который необходимо захватить, и один аргумент для расположения загрузки
  • Обработка происходит в «valuebox-модуле».
  • «Valuebox-модуль» отображает только результаты первого ответа API