rstudio / pins-r

Pin, discover, and share resources
https://pins.rstudio.com
Other
312 stars 63 forks source link

pins_reactive_read does not update when pin changes more frequently than once a minute #542

Closed TylerGrantSmith closed 2 years ago

TylerGrantSmith commented 2 years ago

the pin_reactive_read function sets up a shiny::reactivePoll object using pin_created as the checkFunc. However, this is not ideal, because pin_created only seems to return a timestamp with accuracy to the minute, and so if a pin is updated twice within the same minute, the reactive is never triggered. Wouldn't it make more sense to use the hash value? Here is an example shiny app.

pin_hash <- function(name, board) pins::pin_meta(board, name)$pin_hash

custom_pin_reactive_read <- function(board, name, interval) {
  rlang::check_installed("shiny")
  shiny::reactivePoll(intervalMillis = interval, 
                      session = shiny::getDefaultReactiveDomain(), 
                      checkFunc = function() pin_hash(name = name, board = board), 
                      valueFunc = function() pins::pin_read(board = board, name = name))
}

write_time_pin <- function(board) pins::pin_write(board, Sys.time(), "time")

ui <- shiny::fluidPage(shiny::textOutput("pins"),
                       shiny::textOutput("custom"))

server <- function(input, output, session) {
  board <- pins::board_temp()
  write_time_pin(board)
  # update pin once every second
  observe({ 
    write_time_pin(board)
    shiny::invalidateLater(1000)
  })

  pins_pin_reactive_read_value <- pins::pin_reactive_read(board = board, "time", 1000)
  custom_pin_reactive_read_value <- custom_pin_reactive_read(board = board, "time", 1000)
  output$pins <- shiny::renderPrint(req(pins_pin_reactive_read_value()))
  output$custom <- shiny::renderPrint(req(custom_pin_reactive_read_value()))
}

shiny::shinyApp(ui, server)
hadley commented 2 years ago

Yeah, makes sense. Are you interested in doing a PR?

thomaszwagerman commented 2 years ago

Hi @TylerGrantSmith,

I just wanted to say thank you for the code you posted above - it helped me out a lot for a slightly different use case.

In my instance, I'm allowing users to trigger an scheduled markdown (that normally runs hourly) using connectapi, and I wanted to show the time a pin was created to the user to reflect the trigger, however there is no pin_meta() equivalent for pin_reactive_read(), meaning my metadata was out of sync with the data itself.

I've adapted your functions for my use case:

pin_created <- function(board, name) {
  pin_meta(board, name)$created
}

custom_pin_reactive_meta <- function(board, name, interval) {
  rlang::check_installed("shiny")
  shiny::reactivePoll(intervalMillis = interval,
                      session = shiny::getDefaultReactiveDomain(),
                      checkFunc = function() {
                        pin_created(board = board, name = name)
                        },
                      valueFunc = function() {
                        pin_meta(board = board, name = name)
                        })
}

I just thought I'd share this in case it is useful for anyone else.

Some further thoughts are that some flexibility between using pin_hash() and pin_created() should be possible, because a hash only changes if the pins' content changes, but not if it is re-written without changes.

Thanks again!

github-actions[bot] commented 2 years ago

This issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with a reprex: https://reprex.tidyverse.org) and link to this issue.