I have a shiny app deployed on a Linux server. I want the app to timeout if there is no activity for a minute. Based on what I read, I added the line app_idle_timeout to the shiny-server.conf file but I notice that it doesn't work. Can someone please advice how I can ensure that the session times out after a minute? Note: I do NOT have shiny server PRO.
Below is what my shiny-server.conf looks like.
Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;
# Define a server that listens on port 3838
server {
listen 3838;
# Define a location at the base URL
location / {
# Host the directory of Shiny Apps stored in this directory
site_dir /srv/shiny-server;
# Log all Shiny output to files in this directory
log_dir /var/log/shiny-server;
app_idle_timeout 60;
# When a user visits the base URL rather than a particular application,
# an index of the applications available in this directory will be shown.
directory_index on;
}
}
~
Shiny server functions can optionally include session as a parameter (e.g. function(input, output, session) ). The session object is an environment that can be used to access information and functionality relating to the session.
There are many reasons why a shiny app runs slower than expected. The most common reason is the Shiny app code has not been optimized. You can use the profvis package to help you understand how R spends its time. You also might want to make sure your server is large enough to host your apps.
Shiny Server is an open source back end program that makes a big difference. It builds a web server specifically designed to host Shiny apps. With Shiny Server you can host your apps in a controlled environment, like inside your organization, so your Shiny app (and whatever data it needs) will never leave your control.
You can configure your idle
time within the shiny
app like so using some JS, here the app will timeout after 5 seconds.
library(shiny)
library(leaflet)
inactivity <- "function idleTimer() {
var t = setTimeout(logout, 5000);
window.onmousemove = resetTimer; // catches mouse movements
window.onmousedown = resetTimer; // catches mouse movements
window.onclick = resetTimer; // catches mouse clicks
window.onscroll = resetTimer; // catches scrolling
window.onkeypress = resetTimer; //catches keyboard actions
function logout() {
window.close(); //close the window
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(logout, 5000); // time is in milliseconds (1000 is 1 second)
}
}
idleTimer();"
ui <- fluidPage(
tags$script(inactivity),
leafletOutput("mymap")
)
server <- shinyServer(function(input,output,session){
points <- eventReactive(input$recalc, {
cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
}, ignoreNULL = FALSE)
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles(providers$Stamen.TonerLite,options = providerTileOptions(noWrap = TRUE)) %>%
addMarkers(data = points())
})
})
runApp(list(ui = ui, server = server))
@PorkChop, thanks for your very useful answer!
Just for the sake of completeness, here is a slightly modified version of @PorkChop's code which doesen't close the browser tab, but instead only closes the session and leaves a message for the user:
library(shiny)
library(leaflet)
timeoutSeconds <- 5
inactivity <- sprintf("function idleTimer() {
var t = setTimeout(logout, %s);
window.onmousemove = resetTimer; // catches mouse movements
window.onmousedown = resetTimer; // catches mouse movements
window.onclick = resetTimer; // catches mouse clicks
window.onscroll = resetTimer; // catches scrolling
window.onkeypress = resetTimer; //catches keyboard actions
function logout() {
Shiny.setInputValue('timeOut', '%ss')
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(logout, %s); // time is in milliseconds (1000 is 1 second)
}
}
idleTimer();", timeoutSeconds*1000, timeoutSeconds, timeoutSeconds*1000)
ui <- fluidPage(
tags$script(inactivity),
leafletOutput("mymap")
)
server <- shinyServer(function(input,output,session){
observeEvent(input$timeOut, {
print(paste0("Session (", session$token, ") timed out at: ", Sys.time()))
showModal(modalDialog(
title = "Timeout",
paste("Session timeout due to", input$timeOut, "inactivity -", Sys.time()),
footer = NULL
))
session$close()
})
points <- eventReactive(input$recalc, {
cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
}, ignoreNULL = FALSE)
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles(providers$Stamen.TonerLite, options = providerTileOptions(noWrap = TRUE)) %>%
addMarkers(data = points())
})
})
runApp(list(ui = ui, server = server))
This was very helpful to get here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With