feat: бэкапы локальных баз данных

This commit is contained in:
2026-04-21 13:58:52 +03:00
parent b928f4d356
commit 830e9c31a8
5 changed files with 124 additions and 15 deletions

View File

@@ -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)
}
}
)
}