25

I have a simple shiny app that keeps track of the number of times the user has pushed a certain action button (actionButton()), and this total is reported back to the user along with other information.

Now I know that Shiny R creates one R session per app, so if multiple users are accessing the same app simultaneously, they are all working with the same R session. Hence the reported number of action-button presses for user X ends up being the sum of the action-button presses for all users who have accessed the app during the current R session.

I would like to keep the users separate, in a sense creating virtual instances of the app within a single R session.

I understand that when the function shinyserver() is run with the session argument, then a session object is created, and that information about the client's computer is store d in session$clientdata.

Is there some known way to leverage the contents of this object so as to set up and manage files that keep track of the status of the various users who are accessing the app at any given time?

John Paul
  • 12,196
  • 6
  • 55
  • 75
Homer White
  • 733
  • 1
  • 5
  • 14

2 Answers2

36

I think you're mistaken. Shiny, by default, creates one process per Shiny app, but can facilitate an unlimited number of sessions (i.e. "user connections") in a single app/process.

Checkout this chapter of the tutorial for more info on scoping: https://shiny.posit.co/r/articles/improve/scoping/

Basically, anything defined inside of the shinyServer() expression is going to be private to a single user's session. Any variables you put outside of shinySever will be globally shared between all users. So you can just keep your variables (e.g. a counter of clicks) inside of shinyServer() if you don't want them to be shared across sessions.

Cris
  • 325
  • 1
  • 5
  • 20
Jeff Allen
  • 17,277
  • 8
  • 49
  • 70
  • 2
    Yes, you are right. I was putting some code prior to the shinyServer() function, that should have gone inside of it. I hope I can figure out how to "accept" your answer (I'm new to Stackoverflow). – Homer White May 24 '14 at 23:33
  • 1
    @Jeff Allen Thanks for the comment, it is very clear. May I ask how does ShinyServer handle download files for different users? For example, assuming my app allow user to download some generated data based on their inputs. The file is written as .csv through downloadHandler and the file name is set as "data.csv". Then if there are two users are clicking the download button at the same time, will they get their own data file or one of them will overwrite the other's? I learned each user will have his own session, but regarding to write a file, will they have their own path? – Yunzhao Xing Nov 09 '20 at 19:57
  • if the file path is the same then if the second user clicking the save button will overwrite the first. One approach could be to save the csv on unique paths for each user. – Lazarus Thurston Jul 18 '21 at 16:49
  • 3
    Link is now broken, I think the correct one is now https://shiny.rstudio.com/articles/scoping.html – Dubukay Feb 01 '22 at 03:14
0

Eh, while in principle shinyserver should be creating separate user sessions with separate objects, that has not been my experience. I'm not sure why, maybe it's because all my users are on the same VPN? I actually had multiple users login to the app from multiple locations to test this, and yes, they ended up inappropriately sharing data/objects. A hacky way I got around this was to use the session object as you mentioned above for all variables. For example:

session$userData$sometext <- gsub("\\s", "", input$sometext)

session$userData$ab <- paste0(session$userData$a, session$userData$b, collapse = "")

That being said, the particular app I had issues with allows users to edit and update tables so has some complicated reactive logic; it may not be a problem for all apps.

KeelyD
  • 161
  • 4
  • 3
  • I assume some misspecification in your code led to the data exchange between users. Make sure your variables are truly local. For example, variables created within a sourced function end up in the global environment. [More on scoping rules in R Shiny here](https://shiny.rstudio.com/articles/scoping.html). – bathyscapher Mar 17 '22 at 09:13