1

我正在使用 R 包制作 API plumber。这个 API 中的一些端点会从记忆化中受益,所以我也使用了这个memoise包。将两者结合起来非常简单,如本博文所示。我将在这篇文章的示例上建立我的代表。

# test.R
library(memoise)

# Define function ---------------------------------------------------------
add <- function(a, b) {
    a + b
}

# Memoisize function ------------------------------------------------------
add_mem <- memoise(add)

# Define API --------------------------------------------------------------
#* Return the sum of two numbers
#* @param a The first number to add
#* @param b The second number to add
#* @get /add
function(a, b) {
    add(as.numeric(a), as.numeric(b))
}

#* Return the sum of two numbers, use memoise cached results when applicable
#* @param a The first number to add
#* @param b The second number to add
#* @get /addWithMemoise
function(a, b) {
    add_mem(as.numeric(a), as.numeric(b))
}
# R console 1
plumber::plumb(file="test.R")$run(port=50000)
#Running plumber API at http://127.0.0.1:50000
#Running swagger Docs at http://127.0.0.1:50000/__docs__/
# R console 2
httr::GET("http://localhost:50000/add?a=1&b=1") %>% content()
#[[1]]
#[1] 2
httr::GET("http://localhost:50000/addWithMemoise?a=1&b=1") %>% content()
#[[1]]
#[1] 2

所以现在,我想让我的 API 能够处理并发调用。为此,我将使用该promises包,如本博文中所示。结合plumber起来promises也很简单:

# Added in test.R
library(promises)
#* Return the sum of two numbers, use promises
#* @param a The first number to add
#* @param b The second number to add
#* @get /addWithPromise
function(a, b) {
    future_promise({
        add(as.numeric(a), as.numeric(b))
    })
}

我重新启动 API,然后我可以调用这个新端点:

# R console 2
httr::GET("http://localhost:50000/addWithPromise?a=1&b=1") %>% content()
#[[1]]
#[1] 2

现在我想添加一个混合所有内容的端点(plumbermemoisepromises

# Added in test.R

#* Return the sum of two numbers, use promises and memoise cached results when applicable
#* @param a The first number to add
#* @param b The second number to add
#* @get /addWithPromiseMemoise
function(a, b) {
    future_promise({
        add_mem(as.numeric(a), as.numeric(b))
    })
}

我重新启动 API,然后调用它:

# R console 2
httr::GET("http://localhost:50000/addWithPromiseMemoise?a=1&b=1") %>% content()
#$error
#[1] "500 - Internal server error"
#
#$message
#[1] "Error in add_mem(as.numeric(a), as.numeric(b)): attempt to apply non-function\n"
# R console 1
#Unhandled promise error: attempt to apply non-function
#<simpleError in add_mem(as.numeric(a), as.numeric(b)): attempt to apply non-function>

我试图与future_promise's 的envir论点混在一起,但没有成功。我也试过这个:

# Added in test.R

#* Return the sum of two numbers, use promises and memoise cached results when applicable
#* @param a The first number to add
#* @param b The second number to add
#* @get /addWithPromiseMemoiseTest
function(a, b) {
    print(names(environment(add_mem)))
    e <- environment(add_mem)
    future_promise({
        Sys.sleep(10)
        print(add_mem)
        print(class(add_mem))
        print(names(environment(add_mem)))
        environment(add_mem) <- e
        print(names(environment(add_mem)))
        add_mem(as.numeric(a), as.numeric(b))
    })
}

我重新启动 API,然后调用它:

# R console 2
httr::GET("http://localhost:50000/addWithPromiseMemoise?a=1&b=1") %>% content()
#[[1]]
#[1] 2
# R console 1
#[1] "_omit_args"    "_hash"         "_additional"   "_default_args" "_f_hash"       "_cache"        "_f"           
#Memoised Function:
#NULL
#[1] "memoised" "function"
# [1] "...future.startTime"    "...future.oldOptions"   "a"                      "b"                      "setdiff"                "...future.rng"          "e"                      "...future.frame"       
# [9] "...future.conditions"   "...future.mc.cores.old" "...future.stdout"       "add_mem"               
#[1] "_omit_args"    "_hash"         "_additional"   "_default_args" "_f_hash"       "_cache"        "_f" 

它返回正确的结果,并且该部分按预期工作(在端点调用中future_promise添加 10s 后我可以看到,然后从另一个 R 会话调用另一个端点),但该部分似乎不起作用(我可以看到在函数中添加 10s后,两次调用最后一个端点并不会使其更快)。Sys.sleepfuture_promisefuture_promisememoiseSys.sleepadd

编辑:如果我将它与文件系统记忆结合起来,这个解决方案似乎有效:

# Changed in test.R

# Memoisize function ------------------------------------------------------
cache_fs <- cache_filesystem(".")
add_mem <- memoise(add, cache=cache_fs)

但它看起来确实不是一个干净的解决方案。


因此,由于这是一篇很长的帖子,我会清楚地说明我的问题,以防我失去你:
有没有一种干净的方式来组合memoise::memoisepromises::future_promiseplumber端点内?

4

0 回答 0