Skip to content

Commit 2961dae

Browse files
committed
Fix #807
1 parent 6aaaa42 commit 2961dae

File tree

10 files changed

+89
-7
lines changed

10 files changed

+89
-7
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
* Add Google Cloud Storage via `tar_target(..., repository = "gcp")` (#720, @markedmondson1234). Special thanks to @markedmondson1234 for the cloud storage utilities in `R/utils_gcp.R`
1212
* `mermaid.js` static graphs with `tar_mermaid()` (#775, @yonicd).
13+
* Implement `tar_target(..., error = "null")`to allow errored targets to return `NULL` and continue (#807, @zoews). Errors are still registered, those targets are not up to date, and downstream targets have an easier time continuing on.
1314
* Implement `tar_assert_finite()`.
1415
* `tar_destroy()`, `tar_delete()`, and `tar_prune()` now attempt to delete cloud data for the appropriate targets (#799). In addition, `tar_exist_objects()` and `tar_objects()` now report about target data in the cloud when applicable. Add a new `cloud` argument to each function to optionally suppress this new behavior.
1516
* Add a `zoom_speed` argument to `tar_visnetwork()` and `tar_glimpse()` (#749, @dipterix).

R/class_builder.R

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ builder_handle_error <- function(target, pipeline, scheduler, meta) {
305305
continue = builder_error_continue(target, scheduler),
306306
abridge = scheduler$abridge(target),
307307
stop = builder_error_exit(target, pipeline, scheduler, meta),
308+
null = builder_error_null(target, pipeline, scheduler, meta),
308309
workspace = builder_error_exit(target, pipeline, scheduler, meta)
309310
)
310311
}
@@ -326,6 +327,17 @@ builder_error_exit <- function(target, pipeline, scheduler, meta) {
326327
tar_throw_run(target$metrics$error)
327328
}
328329

330+
builder_error_null <- function(target, pipeline, scheduler, meta) {
331+
target_ensure_buds(target, pipeline, scheduler)
332+
record <- target_produce_record(target, pipeline, meta)
333+
record$data <- "error"
334+
meta$insert_record(record)
335+
target_patternview_meta(target, pipeline, meta)
336+
pipeline_register_loaded(pipeline, target_get_name(target))
337+
scheduler$progress$register_errored(target)
338+
scheduler$reporter$report_errored(target, scheduler$progress)
339+
}
340+
329341
builder_ensure_workspace <- function(target, pipeline, scheduler, meta) {
330342
if (builder_should_save_workspace(target)) {
331343
builder_save_workspace(target, pipeline, scheduler, meta)
@@ -371,15 +383,15 @@ builder_update_build <- function(target, envir) {
371383
}
372384

373385
builder_resolve_object <- function(target, build) {
374-
if (metrics_terminated_early(target$metrics)) {
386+
if (!builder_should_save(target)) {
375387
return(build$object)
376388
}
377389
store_assert_format(target$store, build$object, target_get_name(target))
378390
store_convert_object(target$store, build$object)
379391
}
380392

381393
builder_ensure_paths <- function(target, path_store) {
382-
if (!metrics_terminated_early(target$metrics)) {
394+
if (builder_should_save(target)) {
383395
tryCatch(
384396
builder_update_paths(target, path_store),
385397
error = function(error) builder_error_internal(target, error, "_paths_")
@@ -413,10 +425,15 @@ builder_update_object <- function(target) {
413425
store_upload_object(target$store)
414426
}
415427

428+
builder_should_save <- function(target) {
429+
error_null <- identical(target$settings$error, "null") &&
430+
metrics_has_error(target$metrics)
431+
!metrics_terminated_early(target$metrics) || error_null
432+
}
433+
416434
builder_ensure_object <- function(target, storage) {
417435
context <- identical(target$settings$storage, storage)
418-
completed <- !metrics_terminated_early(target$metrics)
419-
if (context && completed) {
436+
if (context && builder_should_save(target)) {
420437
tryCatch(
421438
builder_update_object(target),
422439
error = function(error) builder_error_internal(target, error, "_store_")

R/class_options.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,10 @@ options_class <- R6::R6Class(
414414
},
415415
validate_error = function(error) {
416416
deprecate_error_workspace(error)
417-
tar_assert_flag(error, c("stop", "continue", "abridge", "workspace"))
417+
tar_assert_flag(
418+
error,
419+
c("stop", "continue", "abridge", "workspace", "null")
420+
)
418421
},
419422
validate_memory = function(memory) {
420423
tar_assert_flag(memory, c("persistent", "transient"))

R/class_settings.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ settings_validate <- function(settings) {
148148
settings$dimensions
149149
)
150150
tar_assert_chr(settings$iteration)
151-
tar_assert_in(settings$error, c("stop", "continue", "abridge", "workspace"))
151+
tar_assert_in(
152+
settings$error,
153+
c("stop", "continue", "abridge", "workspace", "null")
154+
)
152155
tar_assert_in(settings$memory, c("persistent", "transient"))
153156
tar_assert_lgl(settings$garbage_collection)
154157
tar_assert_scalar(settings$garbage_collection)

R/tar_target.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@
167167
#' but no new targets launch after that.
168168
#' (Visit <https://books.ropensci.org/targets/debugging.html>
169169
#' to learn how to debug targets using saved workspaces.)
170+
#' * `"null"`: The errored target continues and returns `NULL`.
171+
#' The data hash is deliberately wrong so the target is not
172+
#' up to date for the next run of the pipeline.
170173
#' @param memory Character of length 1, memory strategy.
171174
#' If `"persistent"`, the target stays in memory
172175
#' until the end of the pipeline (unless `storage` is `"worker"`,

R/tar_target_raw.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ tar_target_raw <- function(
108108
tar_assert_format(format)
109109
tar_assert_repository(repository)
110110
tar_assert_flag(iteration, c("vector", "list", "group"))
111-
tar_assert_flag(error, c("stop", "continue", "abridge", "workspace"))
111+
tar_assert_flag(
112+
error,
113+
c("stop", "continue", "abridge", "workspace", "null")
114+
)
112115
deprecate_error_workspace(error)
113116
tar_assert_flag(memory, c("persistent", "transient"))
114117
tar_assert_lgl(garbage_collection)

man/tar_option_set.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tar_target.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tar_target_raw.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-class_builder.R

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,46 @@ tar_test("convert dep loading errors into runtime errors", {
543543
expect_equal(tar_objects(), "x3")
544544
expect_true(tar_read(x3))
545545
})
546+
547+
tar_test("error = \"null\"", {
548+
skip_on_cran()
549+
tar_script({
550+
library(targets)
551+
f <- function(x) {
552+
stopifnot(x < 1.5)
553+
x
554+
}
555+
list(
556+
tar_target(x, seq_len(2)),
557+
tar_target(y, f(x), pattern = map(x), error = "null"),
558+
tar_target(z, y)
559+
)
560+
})
561+
tar_make(callr_function = NULL)
562+
branches <- tar_meta(y)$children[[1]]
563+
expect_equal(tar_progress(x)$progress, "built")
564+
expect_equal(tar_progress(y)$progress, "errored")
565+
expect_equal(tar_progress(z)$progress, "built")
566+
progress <- tar_progress()
567+
value <- progress$progress[progress$name == branches[1]]
568+
expect_equal(value, "built")
569+
value <- progress$progress[progress$name == branches[2]]
570+
expect_equal(value, "errored")
571+
expect_equal(tar_read(x), seq_len(2))
572+
expect_equal(unname(tar_read(y)), 1L)
573+
expect_equal(unname(tar_read(z)), 1L)
574+
expect_equal(tar_read_raw(branches[1]), 1)
575+
expect_null(tar_read_raw(branches[2]))
576+
expect_equal(tar_errored(), sort(c("y", branches[2])))
577+
out <- tar_outdated(branches = TRUE, callr_function = NULL)
578+
expect_equal(sort(out), sort(c("y", "z", branches[2])))
579+
tar_make(callr_function = NULL)
580+
expect_equal(tar_progress(x)$progress, "skipped")
581+
expect_equal(tar_progress(y)$progress, "errored")
582+
expect_equal(tar_progress(z)$progress, "skipped")
583+
progress <- tar_progress()
584+
value <- progress$progress[progress$name == branches[1]]
585+
expect_equal(value, "skipped")
586+
value <- progress$progress[progress$name == branches[2]]
587+
expect_equal(value, "errored")
588+
})

0 commit comments

Comments
 (0)