Created
July 30, 2024 17:21
-
-
Save JosiahParry/4734f8b92934ea98ddbb0223a9e1546c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' @export | |
new_schedule_builder <- function() { | |
builder <- list( | |
sec = "0", | |
min = "0", | |
hour = "0", | |
dom = "*", | |
month = "*", | |
dow = "*", | |
year = "*" | |
) | |
structure(builder, class = c("schedule_builder", "list")) | |
} | |
#' @export | |
build <- function(x, ...) { | |
UseMethod("build") | |
} | |
#' @export | |
build.schedule_builder <- function(x, ...) { | |
paste0(unlist(x), collapse = " ") | |
} | |
#' @export | |
with_each_minute <- function(builder, every = NULL) { | |
check_number_whole(every, min = 0, allow_null = TRUE) | |
if (!is.null(every)) { | |
builder[["min"]] <- paste0("*", "/", every) | |
} else { | |
builder[["min"]] <- "*" | |
} | |
builder | |
} | |
#' @export | |
with_each_hour <- function(builder, every = NULL) { | |
check_number_whole(every, min = 0, allow_null = TRUE) | |
if (!is.null(every)) { | |
builder[["hour"]] <- paste0("*", "/", every) | |
} else { | |
builder[["hour"]] <- "*" | |
} | |
builder | |
} | |
#' @export | |
with_each_day_of_month <- function(builder, every = NULL) { | |
check_number_whole(every, min = 0, allow_null = TRUE) | |
if (!is.null(every)) { | |
builder[["dom"]] <- paste0("*", "/", every) | |
} else { | |
builder[["dom"]] <- "*" | |
} | |
builder | |
} | |
#' @export | |
with_each_month <- function(builder, every = NULL) { | |
check_number_whole(every, min = 0, allow_null = TRUE) | |
if (!is.null(every)) { | |
builder[["month"]] <- paste0("*", "/", every) | |
} else { | |
builder[["month"]] <- "*" | |
} | |
builder | |
} | |
#' @export | |
with_each_day_of_week <- function(builder, every = NULL) { | |
if (!is.null(every)) { | |
builder[["dow"]] <- paste0("*", "/", every) | |
} else { | |
builder[["dow"]] <- "*" | |
} | |
builder | |
} | |
#' @export | |
with_seconds <- function(builder, seconds) { | |
# days must be between 1-7 | |
for (second in seconds) { | |
check_number_whole(seconds, min = 0, max = 59) | |
} | |
if (length(seconds) > 1) { | |
seconds <- paste0(seconds, collapse = ",") | |
} | |
builder[["sec"]] <- seconds | |
builder | |
} | |
#' @export | |
with_minutes <- function(builder, minutes) { | |
for (minute in minutes) { | |
check_number_whole(minute, min = 0, max = 59) | |
} | |
if (length(minutes) > 1) { | |
minutes <- paste0(minutes, collapse = ",") | |
} | |
builder[["min"]] <- minutes | |
builder | |
} | |
#' @export | |
with_hours <- function(builder, hours) { | |
for (hour in hours) { | |
check_number_whole(hour, min = 0, max = 23) | |
} | |
if (length(hours) > 1) { | |
hours <- paste0(hours, collapse = ",") | |
} | |
builder[["hour"]] <- hours | |
builder | |
} | |
#' Schedule for each specified day of the week | |
#' @export | |
with_day_of_week <- function(builder, days) { | |
# days must be between 1-7 | |
for (day in days) { | |
check_number_whole(day, min = 1, max = 7) | |
} | |
if (length(days) > 1) { | |
days <- paste0(days, collapse = ",") | |
} | |
builder[["dow"]] <- days | |
builder | |
} | |
#' @export | |
with_day_of_month <- function(builder, days) { | |
# days must be between 1-31 | |
for (day in days) { | |
check_number_whole(day, min = 1, max = 31) | |
} | |
if (length(days) > 1) { | |
days <- paste0(days, collapse = ",") | |
} | |
builder[["dom"]] <- days | |
builder | |
} | |
#' @export | |
format.schedule_builder <- function(x, ...) { | |
NextMethod() | |
} | |
#' @export | |
print.schedule_builder <- function(x, ...) { | |
print(format(x)) | |
invisible(x) | |
} | |
# Validate cron schedule | |
split_cron_schedule <- function(schedule) { | |
check_string(schedule, allow_empty = FALSE, allow_na = FALSE, allow_null = NA) | |
parts <- strsplit(schedule, " ")[[1]] | |
if (!(length(parts) %in% 6:7)) { | |
stop("Invalid cron schedule") | |
} | |
parts | |
} | |
validate_cron_part <- function(part, min = 1, max = 59) { | |
if (part == "*") { | |
return(TRUE) | |
} | |
# if ends in a comma, error | |
if (grepl(",$", part)) { | |
stop("cron part cannot end in a comma") | |
} | |
# check if there is a / divider | |
# if there is, then the first part must be either *, whole number | |
# a number range, or comma separated list of numbers | |
if (grepl("/", part)) { | |
parts <- strsplit(part, "/")[[1]] | |
if (length(parts) != 2) { | |
return(FALSE) | |
} | |
# break into upper and lower part | |
first_part <- parts[[1]] | |
# if ends in a comma, error | |
if (grepl(",$", first_part)) { | |
warning("cron part cannot end in a comma") | |
return(FALSE) | |
} | |
second_part <- as.integer(parts[[2]]) | |
# if its isnt the wid card and doesn't contain | |
if (first_part != "*" && !grepl(",", first_part) && !grepl("-", first_part)) { | |
first_part <- as.integer(first_part) | |
check_number_whole(first_part, min = min, max = max) | |
} | |
if (grepl("-", first_part)) { | |
range_parts <- strsplit(first_part, "-")[[1]] | |
if (length(range_parts) > 2) { | |
warning("Ranges can only have two parts") | |
return(FALSE) | |
} | |
check_number_whole(as.integer(range_parts[[1]]), min = min, max = max) | |
check_number_whole(as.integer(range_parts[[2]]), min = min, max = max) | |
} | |
# no upper limitation on the "every" part | |
check_number_whole(second_part, min = 1) | |
} else { | |
if (grepl("-", part)) { | |
range_parts <- strsplit(part, "-")[[1]] | |
if (length(range_parts) > 2) { | |
stop("Ranges can only have two parts") | |
} | |
check_number_whole(as.integer(range_parts[[1]]), min = min, max = max) | |
check_number_whole(as.integer(range_parts[[2]]), min = min, max = max) | |
} | |
if (part != "*" && !grepl(",", part) && !grepl("-", part)) { | |
check_number_whole(as.integer(part), min = min, max = max) | |
} | |
} | |
TRUE | |
} | |
validate_cron_schedule <- function(schedule) { | |
check_string(schedule) | |
parts <- split_cron_schedule(schedule) | |
if (length(parts) == 6) { | |
c(sec, min, hour, dom, mon, dow) %<-% parts | |
year <- NULL | |
} else { | |
c(sec, min, hour, dom, mon, dow, year) %<-% parts | |
} | |
validate_cron_part(sec) | |
validate_cron_part(min) | |
validate_cron_part(hour, 0, 23) | |
validate_cron_part(dom, 1, 31) | |
validate_cron_part(mon, 1, 12) | |
validate_cron_part(dow, 1, 7) | |
validate_cron_part(dow, 1, 7) | |
if (!is.null(year)) { | |
validate_cron_part(year, 1970, 2100) | |
} | |
TRUE | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment