Как реализовать процедуру очистки в R Shiny?
Например, мое блестящее приложение может открыть соединение с DB
# server.R
db <- dbConnect("SQLite", DB_PATH)
shinyServer(
... # things involving db
)
Теперь, как обеспечить правильное закрытие соединения db
(через dbDisconnect(db)
), когда заканчивается сеанс Shiny? Действительно, следует ли выполнять очистку для каждого клиента, который подключается к серверу, или только один раз?
Я просто опасаюсь, что с одновременным подключением и отключением нескольких приложений для приложения Shiny они оставят оборванные соединения DB, если они не будут правильно очищены. Действительно, клиенты могут отключиться без предупреждения, просто закрыв свои браузеры.
Ответы
Ответ 1
Правильный способ сделать это - назначить функцию, выполняющую очистку с помощью session$onSessionEnded
. Например, в server.R:
cancel.onSessionEnded <- session$onSessionEnded(function() {
dbDisconnect(db)
})
Затем вы можете вызвать cancel.onSessionEnded
, чтобы отменить назначение.
Ответ 2
Rstudio опубликовала серию статей в июне о лучших практиках подключения к базе данных. Простой ответ заключается в использовании пулов (см. здесь и здесь). Чтобы сделать его простым, вы определяете свой пул один раз, и он будет обрабатывать и управлять соединениями, открывая и закрывая их по мере необходимости. Когда приложение отключится, пул автоматически закроет все подключения.
К сожалению, пакет пулов не работает с SQL Server и ODBC. Для этой ситуации (или если вы не хотите использовать пул), они советуют использовать on.exit внутри вашей серверной функции s.
например:
getData <- reactive({
cnxn <- dbConnect(...)
on.exit(dbDisconnect(cnxn))
... # your stuff here
})
Ответ 3
Предыдущие ответы мне не кажутся.
-
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")
})
}
)
Ответ 4
Вы можете использовать on.exit(dbDisconnect(db))
внутри определения функции shinyServer.