Skip to content

Commit

Permalink
Fix #166
Browse files Browse the repository at this point in the history
  • Loading branch information
wlandau-lilly committed Nov 23, 2017
1 parent 0c371b0 commit 9345808
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 19 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Expand Up @@ -35,6 +35,7 @@ export(default_parallelism)
export(default_recipe_command)
export(default_short_hash_algo)
export(default_system2_args)
export(default_trigger)
export(dependency_profile)
export(deps)
export(diagnose)
Expand Down
2 changes: 1 addition & 1 deletion R/config.R
Expand Up @@ -87,7 +87,7 @@ drake_config <- function(
force = FALSE,
clear_progress = FALSE,
graph = NULL,
trigger = "any",
trigger = drake::default_trigger(),
imports_only = FALSE,
skip_imports = FALSE,
skip_safety_checks = FALSE
Expand Down
2 changes: 1 addition & 1 deletion R/make.R
Expand Up @@ -263,7 +263,7 @@ make <- function(
force = FALSE,
return_config = NULL,
graph = NULL,
trigger = "any",
trigger = drake::default_trigger(),
skip_imports = FALSE,
skip_safety_checks = FALSE
){
Expand Down
3 changes: 2 additions & 1 deletion R/meta.R
Expand Up @@ -22,7 +22,8 @@ meta <- function(target, config, store = FALSE) {
)
trigger <- get_trigger(target = target, config = config)
# Need to make sure meta includes all these
# fields by the beginning of build_in_hook().
# fields at the beginning of build_in_hook(),
# but only after drake decides to actually build the target.
if (trigger %in% triggers_with_command()){
meta$command <- get_command(target = target, config = config)
}
Expand Down
16 changes: 14 additions & 2 deletions R/outdated.R
@@ -1,6 +1,12 @@
#' @title Function outdated
#' @description Check which targets are out of date and need to be rebuilt.
#' IMPORTANT: you must be in the root directory of your project.
#' @details \code{outdated()} is sensitive to the alternative triggers
#' described at
#' \url{https://github.com/wlandau-lilly/drake/blob/master/vignettes/debug.Rmd#test-with-triggers}. # nolint
#' For example, even if \code{outdated(...)} shows everything up to date,
#' \code{outdated(..., trigger = "always")} will show
#' all targets out of date.
#' @export
#' @seealso \code{\link{missed}}, \code{\link{workplan}},
#' \code{\link{make}}, \code{\link{vis_drake_graph}}
Expand Down Expand Up @@ -31,13 +37,17 @@
#' which targets are up to date. If \code{FALSE}, the computation
#' is faster, but all the relevant information is drawn from the cache
#' and may be out of date.
#' @param trigger same as for \code{\link{make}}
#' @examples
#' \dontrun{
#' load_basic_example() # Load the canonical example of drake.
#' outdated(my_plan) # Which targets are out of date?
#' make(my_plan) # Run the projects, build the targets.
#' # Now, everything should be up to date (no targets listed).
#' outdated(my_plan)
#' # outdated() is sensitive to triggers.
#' # See the "debug" vignette for more on triggers.
#' outdated(my_plan, trigger = "always")
#' }
outdated <- function(
plan = workplan(),
Expand All @@ -52,7 +62,8 @@ outdated <- function(
prework = character(0),
graph = NULL,
config = NULL,
make_imports = TRUE
make_imports = TRUE,
trigger = drake::default_trigger()
){
force(envir)
if (is.null(config)){
Expand All @@ -67,7 +78,8 @@ outdated <- function(
jobs = jobs,
packages = packages,
prework = prework,
graph = graph
graph = graph,
trigger = trigger
)
}
if (make_imports){
Expand Down
23 changes: 20 additions & 3 deletions R/triggers.R
Expand Up @@ -65,11 +65,25 @@
triggers <- function(){
c(
"any",
"always",
"command",
"depends",
"file",
"missing"
)
) %>%
sort
}

#' @title Function default_trigger
#' @description Return the default trigger.
#' @export
#' @seealso \code{\link{triggers}}, \code{\link{make}}
#' @return A character scalar naming the default trigger.
#' @examples
#' default_trigger()
#' # See ?triggers for more examples.
default_trigger <- function(){
"any"
}

triggers_with_command <- function(){
Expand Down Expand Up @@ -158,6 +172,9 @@ should_build_target <- function(target, meta, config){
}
do_build <- FALSE
trigger <- get_trigger(target = target, config = config)
if (trigger == "always"){
return(TRUE)
}
if (trigger %in% triggers_with_command()){
do_build <- do_build ||
command_trigger(target = target, meta = meta, config = config)
Expand All @@ -176,6 +193,6 @@ should_build_target <- function(target, meta, config){
using_default_triggers <- function(config){
default_plan_triggers <-
is.null(config$plan$trigger) ||
all(config$plan$trigger == "any")
default_plan_triggers && config$trigger == "any"
all(config$plan$trigger == default_trigger())
default_plan_triggers && config$trigger == default_trigger()
}
21 changes: 21 additions & 0 deletions man/default_trigger.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/drake_config.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/make.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion man/outdated.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 15 additions & 4 deletions tests/testthat/test-triggers.R
Expand Up @@ -15,7 +15,7 @@ test_with_dir("triggers work as expected", {
cmd <- con$plan$command[con$plan$target == "combined"]
con$plan$command[con$plan$target == "combined"] <-
"nextone + yourinput + 1"
for (trigger in setdiff(triggers(), triggers_with_command())){
for (trigger in setdiff(triggers(), c("always", triggers_with_command()))){
con$plan$trigger <- trigger
expect_equal(outdated(config = con), character(0))
}
Expand All @@ -29,7 +29,7 @@ test_with_dir("triggers work as expected", {
# Destroy a file target.
file.rename("intermediatefile.rds", "tmp")
check_file <- function(con){
for (trigger in setdiff(triggers(), triggers_with_file())){
for (trigger in setdiff(triggers(), c("always", triggers_with_file()))){
con$plan$trigger <- trigger
expect_equal(outdated(config = con), character(0))
}
Expand All @@ -43,7 +43,9 @@ test_with_dir("triggers work as expected", {

# Restore the file target.
file.rename("tmp", "intermediatefile.rds")
for (trigger in triggers()){
con$plan$trigger <- "always"
expect_equal(sort(outdated(config = con)), sort(con$plan$target))
for (trigger in setdiff(triggers(), "always")){
con$plan$trigger <- trigger
expect_equal(outdated(config = con), character(0))
}
Expand All @@ -70,7 +72,8 @@ test_with_dir("triggers work as expected", {
expect_equal(justbuilt(con), character(0))
})

test_with_dir("'missing' trigger brings targets up to date", {
test_with_dir("'missing' and 'always' triggers", {
# 'missing' trigger brings targets up to date.
con <- dbug()
con <- make(
con$plan, trigger = "missing", parallelism = con$parallelism,
Expand All @@ -82,6 +85,14 @@ test_with_dir("'missing' trigger brings targets up to date", {
envir = con$envir
)
expect_equal(out, character(0))

# 'always' trigger rebuilts up-to-date targets
con$plan$trigger <- "any"
con$plan$trigger[con$plan$target == "final"] <- "always"
con2 <- make(
con$plan, parallelism = con$parallelism,
envir = con$envir, jobs = con$jobs, verbose = FALSE)
expect_equal(justbuilt(con2), "final")
})

test_with_dir("Depends brings targets up to date", {
Expand Down
9 changes: 6 additions & 3 deletions vignettes/debug.Rmd
Expand Up @@ -168,15 +168,16 @@ clean(verbose = FALSE) # Start from scratch
make(my_plan, trigger = "missing")
```

You can choose from a variety of triggers.
You can choose from any of the following triggers for all targets or for each target separately..

- `any`: Build the target if any of the other triggers activate (default).
- `always`: Always build the target regardless of the circumstance, even if the target is already up to date.
- `any`: Apply all the triggers below (default). In other words, trigger a build if the `command` trigger, `depends` trigger, `file` trigger, or `missing` trigger is activated.
- `command`: Build if the workflow plan command has changed since last time the target was built. Also built if `missing` is triggered.
- `depends`: Build if any of the target's dependencies has changed since the last `make()`. Also build if `missing` is triggered.
- `file`: Build if the target is a file and that output file is either missing or corrupted. Also build if `missing` is triggered.
- `missing`: Build if the target itself is missing. Always applies.

You can set separate triggers for individual targets with a `trigger` column in the workflow plan data frame. This overrides the `trigger` argument to `make()`
To define triggers for individual targets, define an optional `trigger` column in the workflow plan data frame. Entries in this column override the `trigger` argument to `make()`

```{r indivtrigger}
my_plan$trigger <- "command"
Expand All @@ -193,6 +194,8 @@ reg2 <- function(d) {
make(my_plan, trigger = "any") # Nothing changes!
```

The `outdated()` function responds to triggers. For example, even if `outdated(my_plan)` shows all targets up to date, `outdated(my_plan, trigger = "always")` will claim that all the targets are outdated.

# Skipping imports

Similar to triggers, another way to speed testing is to skip the imports entirely. However, *you should only use this for testing purposes*. If some of your imports are not already cached and up to date, any built targets will be out of sync. In other words, you risk false positive findings in `outdated()`, and your project may no longer be reproducibly interconnected.
Expand Down

0 comments on commit 9345808

Please sign in to comment.