Conditional Caching Shiny

H!

I am trying to do conditional caching for a shiny app.

Let's suppose that a script for the shiny app occasionally will result in an error that will resolve later in time. If I immediately cache the first-run-results, the resulting solution will not be re-ran as the server logic will first go to the cached version which is problematic if the first run resulted in an error.

Thus, I would like to implement some logic flow allowing for conditional caching.

Yet, it doesn't work and I can't figure out why.

Reproducible Example using moduleServer

library(ggplot2)
library(dplyr)
shinyOptions(cache = cachem::cache_disk("myapp-cache"))

ui <- fluidPage(
  mainPanel(
    textInput(inputId = "test",
              label = "test input",
              value = "yup"),
    
    plotOutput(outputId = 'test_plot') 
  )
)
##
server <- function(input, output, session){
  reactive({input$test}) -> key
  server.create_graph(id = 'test_plot') -> output$test_plot
}

shiny::shinyApp(ui, server)

Second Script:

server.create_graph <- function(id){
  moduleServer(
    id, 
    function(input, output, session){
      renderPlot({
        ## Create random data
        rep(c('a', 'b'), 5) -> error.data
        c(1:10) -> correct.data
        data.frame('error_data' = error.data,
                   'correct_data' = correct.data, 
                   'values' = 1:10) -> test.df
        
        ## Create Plot with randomly chosen
        sample(x = c(1, 2), size = 1) -> random.choice
        test.df[, c(random.choice, 3)] -> graph.df
        ggplot(data = graph.df) +
          geom_line(aes(x = graph.df[, 1], y = graph.df[, 1] - graph.df[, 2])) -> graph.object
        return(graph.object)
      }) %>% bindCache(., input$key)
    }
  )
}


This will appropriately cache all outputs, even if it is the error and not the graph.

But suppose I want to ensure that the output of a graph, and not an error. So I write a function to do just that and then I add it like so:

server.create_graph <- function(id){
  moduleServer(
    id, 
    function(input, output, session){
      renderPlot({
        ## Create random data
        rep(c('a', 'b'), 5) -> error.data
        c(1:10) -> correct.data
        data.frame('error_data' = error.data,
                   'correct_data' = correct.data, 
                   'values' = 1:10) -> test.df
        
        ## Create Plot with randomly chosen
        sample(x = c(1, 2), size = 1) -> random.choice
        test.df[, c(random.choice, 3)] -> graph.df
        ggplot(data = graph.df) +
          geom_line(aes(x = graph.df[, 1], y = graph.df[, 1] - graph.df[, 2])) -> graph.object
        return(graph.object)
      }) %>% checkBefore(., input$key) ## New checking function
    }
  )
}
## Function checks if item is a ggplot class before caching
checkBefore <- function(item, input){
  if('ggplot' %in% class(item)){
    bindCache(item, input)
  }
  return(item)
}

Even when the item is a ggplot, nothing gets cached.

Ideas?

1 Like

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.