【问题标题】:How to implement a cleanup routine in R Shiny?如何在 R Shiny 中实现清理例程?
【发布时间】:2017-10-30 19:23:25
【问题描述】:

例如,我闪亮的应用程序可能会打开数据库连接

# server.R
db <- dbConnect("SQLite", DB_PATH)
shinyServer(
    ...  # things involving db
)

现在,当 Shiny 会话结束时,如何确保连接 db 正确关闭(通过 dbDisconnect(db))?确实,应该为每个连接到服务器的客户端执行清理,还是只执行一次?

我只是担心多个用户一直在连接和断开 Shiny 应用程序,如果没有正确清理,他们会留下悬空的数据库连接。事实上,客户可能会在没有警告的情况下断开浏览器,只需关闭浏览器即可。

【问题讨论】:

标签: r shiny


【解决方案1】:

执行此操作的正确方法是使用session$onSessionEnded 分配一个执行清理的函数。例如,在 server.R 中:

cancel.onSessionEnded <- session$onSessionEnded(function() {
    dbDisconnect(db)
})

然后您可以致电cancel.onSessionEnded 撤消分配。

【讨论】:

  • 这对我有用。如果您只需要在退出时调用该函数,则无需为其命名。
  • 这是如何在当前版本的闪亮中工作的,您有一个脚本(例如,其中定义了 ui 和服务器的 app.R)。连接是在服务器函数定义之外还是在内部?您如何在这两种情况下适当地断开连接?
  • 答案在这里:shiny.rstudio.com/articles/pool-basics.html 在 ui 和服务器功能之外使用 pool 创建连接
  • 我强烈建议不要这样做。这意味着,如果您有两个用户在使用该应用并且一个用户关闭了他们的标签页,那么另一个用户也会失去连接。
  • @DeanAttali 你有这方面的例子吗?如果您在 server() 中创建连接,每个用户不应该失去自己的连接吗?
【解决方案2】:

预先存在的答案对我来说似乎不正确。

  • session$onSessionEnded 可以在每个用户断开连接时关闭连接,但在原始问题中,所有用户只有一个连接。尤其是在使用pool 时,您不想为每个用户启动/停止单独的连接。
  • on.exit 直接运行,不等到服务器退出。

我认为正确的答案是使用onStop (https://shiny.rstudio.com/reference/shiny/latest/onStop.html)。

示例用法,来自文档:

library(shiny)
shinyApp(
  ui = basicPage("onStop demo"),

  server = function(input, output, session) {
    onStop(function() cat("Session stopped\n"))
  },

  onStart = function() {
    cat("Doing application setup\n")

    onStop(function() {
      cat("Doing application cleanup\n")
    })
  }
)

【讨论】:

    【解决方案3】:

    Rstudio 早在 6 月就发布了一系列关于连接到数据库的最佳实践的文章。简单的答案是使用池(参见herehere)。为简单起见,您只需定义一次池,它将处理和管理连接,并根据需要打开和关闭它们。应用断开连接后,连接池会自动关闭所有连接。

    不幸的是,池包不适用于 SQL Server 和 ODBC。对于这种情况(或者如果您不想使用池),他们建议在您的服务器函数中使用 on.exits

    例如:

    getData <- reactive({
    cnxn <- dbConnect(...)
    on.exit(dbDisconnect(cnxn))
    
    ... # your stuff here
    })
    

    【讨论】:

      【解决方案4】:

      您可以在 shinyServer 函数定义中使用on.exit(dbDisconnect(db))

      【讨论】:

      • 在这种情况下,我是否也应该将db &lt;- dbConnect("SQLite", DB_PATH) 放在shinyServer 中?我假设shinyServer 内的任何内容每个客户端执行一次,shinyServer 之外的任何内容仅由服务器执行一次。
      • 我不认为这有什么不同。在任何一种情况下,它都会为每个客户端连接执行一次,无论它是否在 shinyServer 定义内。
      • @tmpname12345,我测试了它,它实际上不起作用:在 runApp 启动时将调用一次 shinyServer。在这种情况下,连接将在第一次运行时关闭,并且在闪亮会话期间不会持续。
      猜你喜欢
      • 2021-11-29
      • 2015-07-30
      • 2019-10-01
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多