feat: бэкапы локальных баз данных
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,10 +1,8 @@
|
||||
/renv
|
||||
/temp
|
||||
/_devel
|
||||
|
||||
scheme.rds
|
||||
configs/schemas/d2tra_t.xlsx
|
||||
configs/schemas/antifib.xlsx
|
||||
/_devel
|
||||
.Renviron
|
||||
.DS_Store
|
||||
.lintr
|
||||
|
||||
44
README.md
44
README.md
@@ -12,6 +12,45 @@
|
||||
|
||||
...
|
||||
|
||||
# Quick start
|
||||
|
||||
## локально:
|
||||
|
||||
Копирование содержимого репозитория
|
||||
```bash
|
||||
git clone https://gitea.madelirihs.ru/madeliri/shiny_form.git
|
||||
```
|
||||
|
||||
Восстановление окружения
|
||||
```r
|
||||
renv::init()
|
||||
```
|
||||
|
||||
# Насторйки
|
||||
|
||||
## переменные окружения
|
||||
|
||||
### работа с авторизацией
|
||||
|
||||
Пароль базы данных с авторизацией необходимо указать в `.Renviron`:
|
||||
```
|
||||
AUTH_DB_KEY = "this_is_your_password"
|
||||
```
|
||||
|
||||
### бэкапы локальных баз
|
||||
|
||||
Для создания бэкапов локальных баз данных, необходимо указать путь куда будут сохранятся бэкапы в переменной окружения:
|
||||
```
|
||||
FORM_APP_LOCAL_DB_BACKUP_PATH="path_to_backups"
|
||||
```
|
||||
|
||||
Проверка осуществляется при каждом запуске приложения, бэкапы создаются раз в день (при первом запуске).
|
||||
|
||||
Количество сохраняемых бэкапов:
|
||||
```
|
||||
FORM_APP_LOCAL_DB_BACKUP_LIMITS=3
|
||||
```
|
||||
|
||||
|
||||
# Cтруктура `schema.xlsx`
|
||||
|
||||
@@ -41,11 +80,6 @@
|
||||
|
||||
## Авторизация
|
||||
|
||||
Пароль базы данных с авторизацией необходимо указать в `.Renviron`:
|
||||
|
||||
```
|
||||
AUTH_DB_KEY = "this_is_your_password"
|
||||
```
|
||||
|
||||
# trade-ofs
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
default:
|
||||
form_app_version: 0.15.0
|
||||
form_id: new_formy
|
||||
form_name: NEW FORMY
|
||||
|
||||
prod:
|
||||
form_app_configure_path: "."
|
||||
form_auth_enabled: true
|
||||
form_id: new_formy
|
||||
form_name: NEW FORMY
|
||||
|
||||
devel:
|
||||
form_app_configure_path: _devel/d2tra
|
||||
form_auth_enabled: false
|
||||
form_id: new_formy
|
||||
form_name: NEW FORMY
|
||||
form_app_version: 0.15.0 dev
|
||||
68
modules/db.R
68
modules/db.R
@@ -336,3 +336,71 @@ excel_to_db_dates_converter = function(date) {
|
||||
fin_date <- as.character(format(fin_date, "%Y-%m-%d"))
|
||||
fin_date
|
||||
}
|
||||
|
||||
#' @export
|
||||
local_db_backup <- function(
|
||||
db_name,
|
||||
backups_paths = Sys.getenv("FORM_APP_LOCAL_DB_BACKUP_PATH"),
|
||||
backups_limit = as.integer(Sys.getenv("FORM_APP_LOCAL_DB_BACKUP_LIMITS", 5))
|
||||
) {
|
||||
|
||||
db_path <- fs::path(config::get("form_app_configure_path"), "db")
|
||||
db_full_path <- fs::path(db_path, db_name, ext = "sqlite")
|
||||
|
||||
backup_folder <- fs::path(backups_paths, db_name)
|
||||
|
||||
if (!dir.exists(backup_folder)) dir.create(backup_folder, recursive = TRUE)
|
||||
|
||||
date_mark <- format(Sys.time(), "%Y%m%d")
|
||||
|
||||
schedule <- c(
|
||||
daily = 1,
|
||||
weekly = 7,
|
||||
monthly = 28
|
||||
)
|
||||
|
||||
purrr::walk2(
|
||||
.x = schedule,
|
||||
.y = names(schedule),
|
||||
.f = \(schedule_days, schedule_name) {
|
||||
|
||||
# daily
|
||||
daily_folder <- fs::path(backup_folder, schedule_name)
|
||||
todays_backup <- fs::path(daily_folder, paste0(db_name, "_", format(Sys.time(), "%Y%m%d")), ext = "sqlite")
|
||||
|
||||
if (!dir.exists(daily_folder)) dir.create(daily_folder)
|
||||
|
||||
existed_files <- fs::dir_ls(daily_folder, regexp = "((?:19|20)\\d\\d)(0?[1-9]|1[012])([12][0-9]|3[01]|0?[1-9])")
|
||||
existed_files <- sort(existed_files, decreasing = TRUE)
|
||||
|
||||
# если бэкап для сегодняшнего дня есть - скипаем процедуру
|
||||
if (todays_backup %in% existed_files) {
|
||||
return()
|
||||
}
|
||||
|
||||
# парсим даты
|
||||
dates <- stringr::str_extract(existed_files, "((?:19|20)\\d\\d)(0?[1-9]|1[012])([12][0-9]|3[01]|0?[1-9])")
|
||||
dates <- as.Date(dates, "%Y%m%d")
|
||||
|
||||
# если количество существующих бэкапов значимо превышает установленный лимит, удаляем лишнее
|
||||
if (length(existed_files) > backups_limit) {
|
||||
file.remove(utils::tail(existed_files, length(existed_files) - backups_limit))
|
||||
}
|
||||
|
||||
# если количество существующих бэкапов равно имеющемуся и пора делать бэкап - делаем бэкап, удаляем послендий файл
|
||||
if (length(existed_files) >= backups_limit & dates[1] + schedule_days == Sys.Date()) {
|
||||
|
||||
file.remove(utils::tail(existed_files, 1))
|
||||
file.copy(db_full_path, todays_backup)
|
||||
|
||||
} else if(length(existed_files) == 0) {
|
||||
|
||||
file.copy(db_full_path, todays_backup)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,13 @@ check_and_init_scheme = function() {
|
||||
|
||||
cli::cli_inform(c("*" = "проверка схемы..."))
|
||||
|
||||
options(box.path = here::here())
|
||||
box::use(modules/db[local_db_backup])
|
||||
|
||||
options(box.path = config::get("form_app_configure_path"))
|
||||
box::use(configs/enabled_schemes[enabled_schemes])
|
||||
|
||||
# список файлов, изменение которых, приведут к переинициализиации схемы
|
||||
files_to_watch <- c(
|
||||
fs::path(config::get("form_app_configure_path"), "configs", "enabled_schemes.R"),
|
||||
"modules/scheme_generator.R",
|
||||
@@ -53,7 +57,9 @@ check_and_init_scheme = function() {
|
||||
scheme_file <- paste0(config::get("form_app_configure_path"), "/configs/schemas/", scheme_names, ".xlsx")
|
||||
scheme_file <- stats::setNames(scheme_file, scheme_names)
|
||||
|
||||
if (!all(file.exists(scheme_file))) cli::cli_abort(c("Отсутствуют файлы схем для следующих наименований:", paste("-", names(scheme_file)[!file.exists(scheme_file)])))
|
||||
if (!all(file.exists(scheme_file))) {
|
||||
cli::cli_abort(c("Отсутствуют файлы схем для следующих наименований:", paste("-", names(scheme_file)[!file.exists(scheme_file)])))
|
||||
}
|
||||
|
||||
db_files <- paste0(config::get("form_app_configure_path"), "/db/", scheme_names, ".sqlite")
|
||||
|
||||
@@ -71,8 +77,6 @@ check_and_init_scheme = function() {
|
||||
} else {
|
||||
|
||||
saved_hash <- readRDS(hash_file)
|
||||
print(exist_hash)
|
||||
print(saved_hash)
|
||||
|
||||
# если данные были изменены проводим реинициализацию таблицы и схемы
|
||||
if (!all(exist_hash == saved_hash)) {
|
||||
@@ -85,6 +89,13 @@ check_and_init_scheme = function() {
|
||||
}
|
||||
}
|
||||
|
||||
# MAKING BACKUPS
|
||||
if (Sys.getenv("FORM_APP_LOCAL_DB_BACKUP_PATH") != "") {
|
||||
cli::cli_inform(c("*" = "создание бэкапов баз данных..."))
|
||||
purrr::walk(scheme_names, local_db_backup)
|
||||
|
||||
}
|
||||
|
||||
# перезаписываем файл
|
||||
if (!dir.exists("temp")) dir.create("temp")
|
||||
saveRDS(exist_hash, hash_file)
|
||||
|
||||
Reference in New Issue
Block a user