-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Config reader with expected schema validation #7
Changes from all commits
a7602bb
51b5a25
981e158
a006e91
4611b3e
5a6e5b8
88713ec
33f0d6c
14f0eba
17dbb3b
db850c4
4693447
f047717
1e6fbb2
f27ed7a
a72c5ba
5e25426
3f7e043
76ac3fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ Imports: | |
duckdb, | ||
EpiNow2 (>= 1.4.0), | ||
jsonlite, | ||
jsonvalidate, | ||
rlang, | ||
rstan, | ||
tidybayes | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#' Fetch the config from an external resource | ||
#' | ||
#' This step is the first part of the modeling pipeline. It looks to Azure Blob | ||
#' and downloads the Rt model run's config to the local config (if | ||
#' `blob_storage_container` is specified), reads the config in from the | ||
#' filesystem, and validates that it matches expectations. If any of these steps | ||
#' fail, the pipeline fails with an informative error message. Note, however, | ||
#' that a failure in this initial step suggests that something fundamental is | ||
#' misspecified and the logs will likely not be preserved in a Blob Container if | ||
#' running in Azure. | ||
#' | ||
#' The validation relies on `inst/data/config_schema.json` for validation. This | ||
#' file is in `json-schema` notation and generated programatically via | ||
#' https://www.jsonschema.net/. | ||
#' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. General comment, I think these are all character strings but I find it helpful when reading documentation when the type is explicitly specified. |
||
#' @param config_path The path to the config file, either in the local | ||
#' filesystem or with an Azure Blob Storage container. If | ||
#' `blob_storage_container` is specified, the path is assumed to be within | ||
#' the specified container otherwise it is assumed to be in the local | ||
#' filesystem. | ||
#' @param local_dest The local directory to write the config to when downloading | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if |
||
#' it from `blob_storage_container`. This argument is ignored unless | ||
#' `blob_storage_container` is specified. | ||
#' @param blob_storage_container The storage container holding the config at | ||
#' `config_path` | ||
#' @param config_schema_path The path to the file holding the schema for the | ||
#' config json for the validator to use. | ||
#' | ||
#' @return A list of lists, the config for the run. | ||
#' @export | ||
fetch_config <- function( | ||
config_path, | ||
local_dest, | ||
blob_storage_container, | ||
config_schema_path = system.file("extdata/config_schema.json", | ||
natemcintosh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
package = "CFAEpiNow2Pipeline" | ||
)) { | ||
if (!rlang::is_null(blob_storage_container)) { | ||
download_from_azure_blob( | ||
config_path, | ||
local_dest, | ||
container_name = blob_storage_container | ||
) | ||
} else { | ||
cli::cli_alert( | ||
"No blob storage container provided. Reading from local path." | ||
) | ||
} | ||
|
||
cli::cli_alert_info("Loading config from {.path {config_path}}") | ||
validate_config(config_path, config_schema_path) | ||
|
||
config <- rlang::try_fetch( | ||
jsonlite::read_json(config_path), | ||
error = function(con) { | ||
cli::cli_abort( | ||
"Error loading config from {.path {config_path}}", | ||
parent = con, | ||
class = "CFA_Rt" | ||
) | ||
} | ||
) | ||
|
||
return(config) | ||
} | ||
|
||
#' Compare loaded JSON against expectation in `inst/data/config-schema.json` | ||
#' | ||
#' @inheritParams fetch_config | ||
#' @return NULL, invisibly | ||
#' @export | ||
validate_config <- function( | ||
config_path, | ||
config_schema_path = system.file("extdata/config_schema.json", | ||
package = "CFAEpiNow2Pipeline" | ||
)) { | ||
is_config_valid <- rlang::try_fetch( | ||
jsonvalidate::json_validate( | ||
json = config_path, | ||
schema = config_schema_path, | ||
engine = "ajv", | ||
verbose = TRUE, | ||
greedy = TRUE, | ||
error = TRUE | ||
), | ||
error = function(con) { | ||
cli::cli_abort( | ||
c( | ||
"Error while validating config", | ||
"!" = "Config path: {.path {config_path}}", | ||
"!" = "Schema path: {.path {config_schema_path}}" | ||
), | ||
parent = con, | ||
class = "CFA_Rt" | ||
) | ||
} | ||
) | ||
|
||
invisible(is_config_valid) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"fundamental" is quite vague