library(jobqueue)
jq <- jobqueue()
my_job <- jq$run({ 42 })
# === A 'jobqueue'-style callback ============
my_job$on('done', ~message('Result = ', .$result))
#> Result = 42
# === A 'promises'-style callback ============
my_job %...>% message('Result = ', .)
#> Result = 42
See also vignette('hooks')
When expr
is finished evaluating, the result is assigned
to <job>$output
.
By default, <job>$result
will return the exact
same value as <job>$output
.
However, while <job>$output
is a fixed value,
<job>$result
is highly configurable. Most notably by
the reformat
and signal
parameters.
Use reformat = function (job) {...}
to define what
should be returned by <job>$result
.
Important
You may access
job$output
in yourreformat
function.
DO NOT accessjob$result
, which would start an infinite recusion.
reformat
can be set in several places:
jobqueue(reformat = http_wrap)
<jobqueue>$run(reformat = http_wrap)
<job>$reformat <- http_wrap
job
Details<job>$output
blocks until the job
is
done. If you want <job>$result
to not block, you can
return a placeholder value instead.
By default, errors and interrupts will be caught by the
jobqueue
and returned as a condition object from
<job>$result
.
expr <- quote(stop('error XYZ'))
job <- jq$run(expr)
x <- job$result
inherits(x, 'condition')
#> TRUE
x
#> <simpleError in eval(expr, envir, enclos): error XYZ>
If you want those errors to continue propagating, set
signal = TRUE
.
job <- jq$run(expr, signal = TRUE)
x <- job$result
#> Error:
#> ! stop("error XYZ")
#> Caused by error:
#> ! error XYZ
#> Run `rlang::last_trace()` to see where the error occurred.
These signals can be caught as usual by try()
and
tryCatch()
.
print_cnd <- function (cnd) cli::cli_text('Caught {.type {cnd}}.')
job <- jq$run({ Sys.sleep(5) }, signal = TRUE)$stop()
res <- tryCatch(job$result, error = print_cnd, interrupt = print_cnd)
#> Caught an <interrupt> object.
res
#> NULL
job <- jq$run({ stop('error XYZ') }, signal = TRUE)
res <- tryCatch(job$result, error = print_cnd, interrupt = print_cnd)
#> Caught an <error> object.
res
#> NULL
You can also signal some conditions while catching others. Perhaps stopping a job is part of the “normal” workflow and shouldn’t be lumped in with other errors.
You can pass a job
directly to any function that expects
a promise
object, such as promises::then
or
promises::%...>%
. These functions are re-exported by
jobqueue
, so calling library(promises)
is
optional.
By default, errors and interrupts are caught by jobqueue
and used for promise fulfillment.
onFulfilled <- function (value) cli::cli_text('Fulfilled with {.type {value}}.')
onRejected <- function (err) cli::cli_text('Rejected with {.type {err}}.')
job <- jq$run({ Sys.sleep(5) })$stop()
job %>% then(onFulfilled, onRejected)
#> Fulfilled with an <interrupt> object.
job <- jq$run({ stop('error XYZ') })
job %>% then(onFulfilled, onRejected)
#> Fulfilled with an <error> object.
Setting signal = TRUE
will cause errors and interrupts
be sent to the promise’s rejection handler instead.