为什么 future::future() 不能与闪亮的 dbAppendTable 一起使用?

why does future::future() not work with dbAppendTable in shiny?

你可以使用 future() 来解决它的副作用,例如写入文件:

library(promises)
library(future)
plan(multiprocess)
future({write.csv(mtcars,"mtcars.csv")})

但是你不能使用数据库调用:

library(RSQLite)
library(promises)
library(future)
plan(multiprocess)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
future({
dbCreateTable(con, "iris", iris)
})
dbReadTable(con, "iris") # gives error

(table无论是持久化写入还是内存中都不会创建。)

我可能错了,但我怀疑这两个 con 不一样,所以我猜想未来就像宿醉的曼谷:未来发生的事情留在未来未来。可以说,您的 con 是按值(而不是按引用)求值的,因此 table 没有写入原始 con。考虑以下代码:

library(future)
x <- 4
a <- future({
    x <- x + 1 # I am not seen outside
})
x # is still 4 and has not changed
#> [1] 4
value(a) # is 5
#> [1] 5

但是,如果您在 future 中使用 substitute = FALSEx 也将是 5,我很乐意知道原因:-)

DBI 包及其所有实现(如 RSQLite)确实使用 不可导出对象(基本上是内存指针),请参阅:

https://cran.r-project.org/web/packages/future/vignettes/future-4-non-exportable-objects.html

当您像这样配置 futures 时,您会看到一条错误消息:

options(future.globals.onReference = "error")
# ... your code goes here

# Error in FALSE : 
# Detected a non-exportable reference (‘externalptr’) in one of the globals (‘con’ of class ‘SQLiteConnection’) used in the future expression
# Timing stopped at: 0.028 0 0.028

将 futures 与数据库连接一起使用时,您必须在 future 中创建(并可能关闭)连接:

library(RSQLite)
library(promises)
library(future)
plan(multiprocess)

future({
con <- dbConnect(RSQLite::SQLite(), ":memory:")
on.exit(DBI::dbDisconnect(con))
dbCreateTable(con, "iris", iris)
})
# reconnect and read
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbReadTable(con, "iris") 
#data frame with 0 columns and 0 rows

github

上有一个未解决的问题