we're using RStudio Connect in our company (migrated from Shiny Server Pro) and we're running into some issues with package management (e.g. updates) - FYI, the packages are being loaded in global.R (outside server function).
Our workflow looks like this:
develop code
write manifest.json (rsconnect::writeManifest())
deploy to RStudio Connect (use manifest.json to install packages and place bundle onto the server)
What we're currently observing is that processes which had started prior to the deployment (package updates) are using the original package versions (presuming they're loaded in memory) - this is expected.
The issue arises when user tries to access the app after we've updated he packages (e.g. by navigating to it or refreshing browser window) and instead of starting-up a completely new process, the server seems to recycle one of the existing processes (potentially one that started before package have been updated), which results in user seeing the "old version" of the app.
What we'd like to achieve here is basically an app restart that would guarantee the server will force-start new processes after deployment (package updates) or otherwise reload updated packages. This should preferrably be available in a programmatic fashion (e.g. API) so it can be part of the deployment process itself. Also, it would be great (but not essential) if we won't need to kill all existing processes to achieve this.
We're bringing this up, because we're using similar functionality in Shiny Server Pro: https://docs.rstudio.com/shiny-server/#restarting-an-application - where the deployment job makes sure to update the "restart.txt" file, forcing the app to start a new process upon a new connection.
I found the following by poking around. Each app has its own number in the directory /var/lib/rstudio-connect/apps. Under that are consecutively incremented deploy numbers (2/29 below.) Use fuser or lsof to get the proc from the previous build's directory and kill them.
sudo fuser -fv /var/lib/rstudio-connect/apps/2/29
USER PID ACCESS COMMAND
root 20165 ..c.. timestamper
rstudio-connect 20170 ..c.. R
Thanks so much for reporting this!! We will take a look at this internally and see if there is a nice way to force apps to recycle. In the meantime, you can do this yourself a few different ways. The simplest is probably creating a dummy environment variable or changing its value. This will force all processes of the app to restart.
Do you mind giving that a try and letting us know if it solves your problem?
Thanks for the suggestion! We'll definitely try it out and let you know how that worked out. One question though, if you say "force all processes of the app to restart", does it mean those processes will be killed?
Yes. I'm curious how that feels to you Does that fit your needs? Are you looking for something more nuanced - only killing/restarting the old processes? The processes are restarted so that the new environment variables can take effect.
Yes, for us it is all about killing the out of date processes. We pre-load global variables with a lot of processed data (8-10G sometimes) in order to make our applications much more responsive. Ideally, after either a deploy or data update we would like to be able to remove the old proc and have rsconnect immediately respawn a new one. Is there a way to kill the old process programmatically during/after a code or data update via the API?
I'd prefer to avoid the putenv, setenv potential issues:
So I believe that stackexchange issue is talking about changing environment variables of a running process. If you change an environment variable in the Vars pane of the RStudio Connect UI, Connect will kill all processes associated with the application (old and new). The environment variable will be provided to the new processes, but the environment variable itself doesn't matter. It could be DUMMY=hello, for instance.
There is not a way through RStudio Connect itself to kill individual processes associated with an application (or the old ones). However, it is possible to kill all processes associated with an application during the code or data update / etc. (by setting an environment variable, as I mentioned above).
There is an experimental R package that utilizes our internal API for this functionality. If you need a programmatic solution, this might be an option:
library(connectapi)
client <- connect()
myapp <- content_item(client, "my-guid")
# this will restart all processes associated with an application by setting a dummy environment variable for new processes
myapp %>%
get_environment() %>%
set_environment_new(DUMMY = "hello")