I have access to a plumber
API which handles some automatic pipelining workflows for me. However, every job runs on the same R session and I'm a bit concerned regarding different calls interfering with each other.
Off to top of my head the wish is that every call starts on a fresh R session. When regularly programming in R I would just restart the session and have a clean setup but with the plumber
server this seems to be "not so easy". Some reading also revealed that "cleaning up" your R session without a restart isn't a straight forward thing.
Of course I'm also open to alternative suggestions. Any suggestions and insights are welcome. In the end I would simply like the API calls to return the same thing if the inputs are the same.
As suggested in the comments by Konrad Rudolph, callr
does the job very well.
Doing 1.-3. (see code chunk) several times for different packages will show that every run is performed in a fresh R session (see process_id) and hence that the search paths are independent.
# put this code into the file plumber.R and run:
# plumber::plumb("plumber.R")$run(port=9999)
# 1. click "Try it out"
# 2. enter a package name that you want to try
# 3. click "Execute"
#* @get /search_path
#* @param lib library to load
function(lib) {
# callr runs the anonymous function in a fresh session
rp <- callr::r_bg({
function(lib) {
library(package = lib, character.only = TRUE)
return(list(search_path = search(),
process_id = Sys.getpid(),
the_time = Sys.time()))
}
},
args = list(lib = lib))
# wait for a result with 30 seconds timeout
rp$wait(30000)
if(rp$is_alive() == TRUE) {
rp$kill()
stop("time exceeded")
}
# return the result
rp$get_result()
}
A bit offtopic but maybe also interesting in this context: Allowing parallel requests can be enabled via the future
package.
# submit two requests for packages within less than 10 seconds of
# each other and compare the time stamps to see that they were processed
# in parallel and in different sessions
future::plan(future::multisession)
#* @get /search_path
#* @param lib library to load
function(lib) {
future::future({
# callr runs the anonymous function in a fresh session
rp <- callr::r_bg({
function(lib) {
Sys.sleep(10)
library(package = lib, character.only = TRUE)
return(list(search_path = search(),
process_id = Sys.getpid(),
the_time = Sys.time()))
}
},
args = list(lib = lib))
# wait for a result with 30 seconds timeout
rp$wait(30000)
if(rp$is_alive() == TRUE) {
rp$kill()
stop("time exceeded")
}
# return the result
rp$get_result()
}, seed = TRUE)
}