rstudio / pins-r

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

Inconsistent Read Time for Pinned Table in R Shiny App with RConnect #755

Closed LukasB1337 closed 1 year ago

LukasB1337 commented 1 year ago

I have developed an R Shiny App hosted using rconnect. The app uses the pins library to store user inputs in a table, which is then pinned to my rconnect board. On app start, the pinned table is read to retrieve existing data and display it. Surprisingly, the initial read operation after this "initial read" takes an unexpectedly long time of around 15 minutes, but subsequent reads and all subsequent operations take only about 1 second.

Here are the steps that occur:

App starts, the pin is read, and the data is displayed (1 second). The user inputs data and clicks "save changes". The saving process begins: The current version of the pin is read again to ensure no other user made changes. A row with the user inputs is appended to the dataframe created from the previously read pin. The pin is overwritten with the new appended table. The issue arises during step 1 of the saving process (reading the pin again) after a prolonged period of not using the app. This initial read operation takes 15 minutes, but subsequent reads, even if the app is closed and reopened, only take 1 second. This problem occurs only after several hours of app inactivity.

I would appreciate any assistance in understanding why the initial read takes significantly longer than subsequent reads, especially since the pin was already read at app start, making it technically the second read.

The pin has a type of "qs". Here is the code for my saving function:


save_changes <- function(df) {

    cat(paste(Sys.time(), "Start reading pin \n"))
    current_pin <- pin_read(board, "PIN-NAME")
    cat(paste(Sys.time(), "Pin read \n"))

    pin_to_save <- rbind(current_pin, df)
    cat(paste(Sys.time(), "Writing ", nrow(pin_to_save), "rows as a new Pin. Starting... \n"))
    pin_write(board, pin_to_save, name = "PIN-NAME", title = "PIN-TITLE", type = "qs")
    cat(paste(Sys.time(), "Finished. \n"))

    return("Saved")

}

The console output typically looks like this:

2023-06-30 07:36:51 Start reading pin 
2023-06-30 07:36:51 Pin read 
2023-06-30 07:36:51 Writing  7 rows as a new Pin. Starting... 
2023-06-30 07:36:52 Finished. 

And after a longer period of app inactivity:

2023-06-30 05:17:10 Start reading pin 
2023-06-30 05:33:27 Pin read 
2023-06-30 05:33:27 Writing  7 rows as a new Pin. Starting... 
2023-06-30 05:33:27 Finished.

I can reproduce this issue by simply not using the app for some time. Currently, I am the only user of this app. If I'm starting the app locally from my laptop, everything works fine (exactly like after deploying and not waiting).

Could someone please assist me in understanding why this one read takes so long and provide any suggestions for resolving this issue?

I tried deleting and recreating the pin. I tried redeploying the app. I tried all pin types.

EDIT: I played around and tried the following: Instead of use the "save" function above, I simply reloaded the board. And I have the exact same issue! board <- board_connect("envvar", server = MY_SERVER, key = connectAPIKey) is also running ~15 mins, even though I'm using this exact code on app start to read the pin. But to me it looks like this: If a pins-function gets triggered by observe_event, it will take ~15 mins (if the app hasn't been used for a while and hasn't been recently published).

juliasilge commented 1 year ago

Wow, that sounds pretty wild! Sounds like something is not happy between Shiny and pins caching, maybe?

LukasB1337 commented 1 year ago

Thanks for your response! Your suggestions regarding the cache were sufficient to identify the cause of the error and find a workaround, although I'm still unsure about what exactly happened.

It turned out that the app was configured to maintain a minimum of 4 active processes, even though the processes were set to time out after 60 minutes. As a result, some processes that should have been terminated were kept alive. When opening the app after more than 60 minutes, instead of creating a new process, it would redirect to one that should have been terminated but was kept alive due to the "minimum processes" setting in rconnect. The issue was resolved by setting the minimum processes to 0.

I'm still uncertain why the initial load of the pin worked fine, and only the first manually triggered load caused an issue. During my investigation, I simplified triggering the pins functions as much as possible:

observeEvent(input$reloadPin, {
    captured_strings <- capture.output({
        cat(paste(Sys.time(), "Starting to load \n"))
        a <- pin_read(board, "PIN_NAME")
        cat(paste(Sys.time(), "Loading finished \n"))
    })
    value(paste(captured_strings, collapse = "\n"))
})

observeEvent(input$reloadBoard, {
    captured_strings <- capture.output({
        cat(paste(Sys.time(), "Reloading board \n"))
        connectAPIKey <- Sys.getenv("connectAPIKey")
        board <<- board_connect("envvar", key = connectAPIKey, server = "SERVER")
        cat(paste(Sys.time(), "Board reloaded \n"))
    })
    value(paste(captured_strings, collapse = "\n"))
})

I opted not to use pin_reactive_read() because I don't anticipate more than 2 users working simultaneously, and there's no need to see other users' input in real-time. Therefore, it seemed more efficient to simply re-read the pin during saving to check for other inputs once, rather than using pin_reactive_read().

I'm using pins 1.2.0 with R 4.2.1

Once again, thank you! This package is truly amazing.

juliasilge commented 1 year ago

Thank you for reporting what happened in your situation! I have surfaced this to the Connect team to see if this unexpected behavior can be addressed.

juliasilge commented 1 year ago

Thanks again for reporting this! It's been surfaced to the Connect team and we'll see if we can address this on the Connect side.

github-actions[bot] commented 1 year 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.