I'm working on an app that relies on user-supplied data that can be quite large (up to a few GB). It takes a bit of time to upload and process (essentially uncompress) the data. I'm trying to take advantage of the ExtendedTask class to perform these long-running tasks in a separate R process.
I use an R6 class (Handler) to handle and uncompress the input file in a temporary directory. For the purpose of the example, I made the Handler class very minimalistic and used Sys.sleep() to emulate the time of uncompressing the file. I use a module for the upload button to keep the example as close as my actual app.
I'm a bit clueless how I should use the ExtendedTask for this purpose. Any help is welcome!
Here's an attempt at reproducing my problem:
library(shiny)
library(bslib)
future::plan(future::multisession)
Handler <- R6::R6Class(
"Handler",
private = list(
.file = NULL
),
public = list(
read = function(file) {
Sys.sleep(5)
private$.file <- file
},
file = function() {
private$.file$datapath
}
)
)
mod_upload_ui <- function(id, ...) {
ns <- NS(id)
fileInput(
ns("file"),
label = "Upload a file",
buttonLabel = "Browse files",
placeholder = "No files selected",
...
)
}
mod_upload_server <- function(id, handler) {
moduleServer(id, function(input, output, session) {
promise <- ExtendedTask$new(function(file) {
promises::future_promise(handler$read(file))
})
observeEvent(input$file, {
promise$invoke(input$file)
promise$result()
})
})
}
ui <- fluidPage(
mod_upload_ui("upload"),
input_task_button("btn", "Click me!"),
verbatimTextOutput("text"),
)
server <- function(input, output, session) {
r6 <- Handler$new()
mod_upload_server("upload", r6)
observeEvent(input$btn, {
output$text <- renderPrint(r6$file())
})
}
shinyApp(ui, server)