满足条件后退出水管工 API

Quit a Plumber API once a condition is met

我正在尝试 运行 管道工 API 内联接收输入,一旦接收到正确的输入并满足指定条件,输入将返回到 globalenv 和API 自行关闭,以便脚本可以继续 运行。

我在调用 quit()、stop() 等的 @get 端点内指定了一个条件,none 其中成功关闭了 API。

我尝试使用 future 并行 运行 API 以便父脚本可以关闭 Plumber API。

似乎 Plumber API class 对象中实际上没有关闭 Plumber API 的方法,并且 API 不能从内部封闭。

我已经通过扩展文档、SO 和 Github 问题来寻找解决方案。建议的唯一半相关解决方案是使用 R.Utils::withTimeout 创建一个有时间限制的超时。不过这个方法也是无法关闭的API。

一个简单的用例: 主要脚本:

library(plumber)
code_api <- plumber::plumb("code.R")
code_api$run(port = 8000)

code.R


#' @get /<code>
function(code) {
  print(code)
  if (nchar(code) == 3) {
    assign("code",code,envir = globalenv())
  quit()}
  return(code)
}
#' @get /exit
function(exit){
  stop()
}

输入成功返回到全局环境,但API之后并没有关闭,调用/exit端点后也没有。

关于如何实现这个的任何想法?

您可以通过以下方式查看 Iterative testing with plumber @Irène Steve's, Dec 23 2018

  • trml <- rstudioapi::terminalCreate()
  • rstudioapi::terminalKill(trml)

她文章的摘录(第 3 版的第 2 版):

.state <- new.env(parent = emptyenv()) #create .state when package is first loaded

start_plumber <- function(path, port) {
    trml <- rstudioapi::terminalCreate(show = FALSE)
    rstudioapi::terminalSend(trml, "R\n") 
    Sys.sleep(2)
    cmd <- sprintf('plumber::plumb("%s")$run(port = %s)\n', path, port)
    rstudioapi::terminalSend(trml, cmd)

    .state[["trml"]] <- trml #store terminal name
    invisible(trml)
}

kill_plumber <- function() {
    rstudioapi::terminalKill(.state[["trml"]]) #access terminal name
}

运行 终端中的管道工在某些情况下可能会起作用,但由于我需要访问 R 会话(对于 insertText),我不得不想出不同的方法。虽然不理想,但以下解决方案有效:

# plumber.R
#* Insert 
#* @param msg The msg to insert to the cursor location 
#* @post /insert
function(msg="") {
  rstudioapi::insertText(paste0(msg))
  stop_plumber(Sys.getpid())
}

.state <- new.env(parent = emptyenv())  #create .state when package is first loaded

stop_plumber <- function(pid) {
  trml <- rstudioapi::terminalCreate(show = FALSE)
  Sys.sleep(2) # Wait for the terminal to initialize  
  # Wait a bit for the Plumber to flash the buffers and then send a SIGINT to the R session process,
  # to terminate the Plumber
  cmd <- sprintf("sleep 2 && kill -SIGINT %s\n", pid)
  rstudioapi::terminalSend(trml, cmd)
  .state[["trml"]] <- trml  # store terminal name
  invisible(trml)
  Sys.sleep(2) # Wait for the Plumber to terminate and then kill the terminal
  rstudioapi::terminalKill(.state[["trml"]])  # access terminal name
}