This is a follow-on question from closing the loop on passing the app and data to a Shiny deployment function:
How to use shiny app as a target in drake
I would like to deploy a Shiny app directly from a drake plan as below.
library(drake)
library(shiny)
plan <- drake_plan(
cars_data = mtcars,
deployment = custom_deployment_function(file_in("app.R"), cars_data)
)
custom_shiny_deployment <- function(file, data_input) {
rsconnect::deployApp(
appFiles = file,
appName = "cars",
forceUpdate = TRUE
)
}
Saved as "app.R" in project working directory (the app works outside of drake if data_input <- mtcars) :
shinyApp(
ui = fluidPage(
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am")),
tableOutput("data")
),
server = function(input, output) {
output$data <- renderTable({
data_input[, c("mpg", input$variable), drop = FALSE]
}, rownames = TRUE)
}
)
Logs from shinyapps.io shows "cars_data" from drake is not being passed to the Shiny server "data_input" in the custom_deployment_function environment:
2020-07-14T20:12:57.418989+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:12:57.419186+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:12:57.589960+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:12:57.593223+00:00 shinyapps[2569696]:
2020-07-14T20:12:57.593224+00:00 shinyapps[2569696]: Starting R with process ID: '25'
2020-07-14T20:12:57.628389+00:00 shinyapps[2569696]:
2020-07-14T20:12:57.628390+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:38608
2020-07-14T20:13:14.686424+00:00 shinyapps[2569696]: Running on host: e89f96d02b6e
2020-07-14T20:13:14.691423+00:00 shinyapps[2569696]: Server version: 1.8.4-11
2020-07-14T20:13:14.691436+00:00 shinyapps[2569696]: LANG: en_US.UTF-8
2020-07-14T20:13:14.691436+00:00 shinyapps[2569696]: R version: 4.0.0
2020-07-14T20:13:14.691437+00:00 shinyapps[2569696]: shiny version: 1.5.0
2020-07-14T20:13:14.691467+00:00 shinyapps[2569696]: rmarkdown version: (none)
2020-07-14T20:13:14.691648+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:13:14.691475+00:00 shinyapps[2569696]: knitr version: (none)
2020-07-14T20:13:14.857243+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:13:14.691443+00:00 shinyapps[2569696]: httpuv version: 1.5.4
2020-07-14T20:13:14.895595+00:00 shinyapps[2569696]:
2020-07-14T20:13:14.691480+00:00 shinyapps[2569696]: jsonlite version: 1.7.0
2020-07-14T20:13:14.860404+00:00 shinyapps[2569696]:
2020-07-14T20:13:14.860404+00:00 shinyapps[2569696]: Starting R with process ID: '41'
2020-07-14T20:13:14.895596+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:42022
2020-07-14T20:13:14.691496+00:00 shinyapps[2569696]: RJSONIO version: (none)
2020-07-14T20:13:14.691506+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:15:57.441648+00:00 shinyapps[2569696]: Running on host: a2e664ad9837
2020-07-14T20:15:57.447236+00:00 shinyapps[2569696]: Server version: 1.8.4-11
2020-07-14T20:15:57.447326+00:00 shinyapps[2569696]: R version: 4.0.0
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: knitr version: (none)
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: rmarkdown version: (none)
2020-07-14T20:15:57.447327+00:00 shinyapps[2569696]: shiny version: 1.5.0
2020-07-14T20:15:57.447260+00:00 shinyapps[2569696]: LANG: en_US.UTF-8
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: httpuv version: 1.5.4
2020-07-14T20:15:57.447338+00:00 shinyapps[2569696]: jsonlite version: 1.7.0
2020-07-14T20:15:57.447338+00:00 shinyapps[2569696]: RJSONIO version: (none)
2020-07-14T20:15:57.667089+00:00 shinyapps[2569696]:
2020-07-14T20:15:57.447494+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:15:57.630039+00:00 shinyapps[2569696]: Starting R with process ID: '24'
2020-07-14T20:15:57.626886+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:15:57.447347+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:15:57.630037+00:00 shinyapps[2569696]:
2020-07-14T20:15:57.667090+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:40107
2020-07-14T20:16:14.758082+00:00 shinyapps[2569696]: Warning: Error in renderTable: object 'data_input' not found
2020-07-14T20:16:14.772348+00:00 shinyapps[2569696]: 108: renderTable [/srv/connect/apps/cars/app.R#13]
2020-07-14T20:16:14.772349+00:00 shinyapps[2569696]: 107: func
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]: 94: origRenderFunc
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]: 93: output$data
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]: 13: runApp
2020-07-14T20:16:14.772351+00:00 shinyapps[2569696]: 12: fn
2020-07-14T20:16:14.772351+00:00 shinyapps[2569696]: 7: connect$retry
2020-07-14T20:16:14.772352+00:00 shinyapps[2569696]: 6: eval
2020-07-14T20:16:14.772352+00:00 shinyapps[2569696]: 5: eval
Apologies if this is trivial, but between drake and shiny, it is escaping me.
Now that I see how you are deploying the app, I can say that this is expected behavior. Yes, your custom_shiny_deployment()
has access to the data, but the deployed app does not because rsconnect::deployApp()
does not ship objects from the calling environment. If you want the data to be available to the app, I recommend saving it (and tracking it with file_in()
and file_out()
) then passing it to the appFiles
argument of deployApp()
via custom_shiny_deployment()
.
Your app.R
can stay like it is.
app.R
is the same as what you wrote.
library(shiny)
cars_data <- readRDS("cars_data.RDS")
shinyApp(
ui = fluidPage(
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am")),
tableOutput("data")
),
server = function(input, output) {
output$data <- renderTable({
cars_data[, c("mpg", input$variable), drop = FALSE]
}, rownames = TRUE)
}
)
But from drake
's side, you need something like file_in()
and file_out()
to ensure the correct targets run in the correct order and in response to changes to cars_data.RDS
and app.R
.
library(drake)
plan <- drake_plan(
cars_data = mtcars,
save_cars = saveRDS(cars_data, file_out("cars_data.RDS")),
deployment = rsconnect::deployApp(
appFiles = file_in("app.R", "cars_data.RDS"),
appName = "cars",
forceUpdate = TRUE
)
)
make(plan)
If you really want appFiles
to be NULL
, drake
still needs file_in()
so it knows to depend on physical files.
plan <- drake_plan(
cars_data = mtcars,
save_cars = saveRDS(cars_data, file_out("cars_data.RDS")),
deployment = deploy_app(file_in("cars_data.RDS", "app.R"))
)
deploy_app <- function(...) {
rsconnect::deployApp(
appFiles = NULL,
appName = "cars",
forceUpdate = TRUE
)
}
Either way, I recommend checking the plan with plot()
or vis_drake_graph()
before you run it with make()
. Both plans above show deployment
downstream of the data file (with incoming arrows) which is exactly what we want.
plot(plan)
Without these file markers, there is a chance that drake
will deploy the app before the data is ready to go.
disconnected_plan <- drake_plan(
cars_data = mtcars,
saveRDS(cars_data, "cars_data.RDS"),
deployment = rsconnect::deployApp(
appFiles = NULL,
appName = "cars",
forceUpdate = TRUE
)
)
plot(disconnected_plan)