# Escalation
Error escalation is one of the more interesting features of the erratum. It's the concept of escalating an issue up until it should be dealt with.
# Basics
Take the example below for instance. There a function which we called random.stuff
that might produce an error (in this case 1 chance out of two). This function is called by another, which is in turn called by another which uses the result to either stop code execution (with resolve
) or compute something.
random.stuff <- function(){
s <- sample(1:10, 1)
if(s <= 5)
return(e("That's a problem!"))
return(s)
}
foo <- function(){
results <- random.stuff()
# return the error if results is one
skip(results)
return(results)
}
bar <- function(){
value <- foo()
# resolve the error if needed
resolve(value)
log(value)
}
bar()
2.197225
bar()
Error: That's a problem!
This is in fact very useful when you want to deal with errors somewhat differently, like in a shiny application where you might want to display a notification on error rather than crash or display an ugly error, or in Plumber where you would want to return the error message with status 400-you-messed-up or 500-we-messed-up.
This is, of course, doable without erratum but is rather painful when the error or warning is raised in a deeply nested function.
# Shiny
Shiny applications tend to be user input heavy and these may fail.
The application below takes as input the name of a column from the cars
dataset, this is checked in a function nested in the call stack and makes it such that escalating the error can be tricky. Moreover we don't want use stop
as this simply shows the error in the respective output from which is function is called.
Instead we escalate the error and display a notification if the input is incorrect.
library(shiny)
library(erratum)
getCol <- function(var){
if(!var %in% c("speed", "dist"))
var <- e("Wrong column name")
var
}
getData <- function(var){
col <- getCol(var)
skip(col)
cars[[col]]
}
ui <- fluidPage(
textInput(
"varInput",
"Enter a column name from the `cars` dataset"
),
verbatimTextOutput("varOutput")
)
server <- function(input, output){
output$varOutput <- renderPrint({
data <- getData(input$varInput)
if(is.e(data)){
showNotification(data$message, type = "error")
return(data$message)
}
data
})
}
shinyApp(ui, server)
One could of course place showNotification
in the getCol
function but then this function becomes less portable; it cannot really be used outside of the shiny application and the error cannot be treated differently elsewhere in the application.
getCol <- function(var){
if(!var %in% c("speed", "dist"))
showNotification("Wrong column name")
var
}
# Plumber
In plumber, very similar to what was done in shiny, although at the instead of showing a notification the error can be escalated and handled properly by setting the response status code correctly.
#* Get Uppercase string
#* @param msg The message to turn uppercase
#* @get /upper
function(req, res, msg="") {
uppercase <- parseMessage(msg)
if(is.e(uppercase)){
res$status <- 400L
return(uppercase$message)
}
list(msg = uppercase)
}
parseMessage <- function(msg){
msg <- checkMessage(msg)
skip(msg)
toupper(msg)
}
checkMessage <- function(msg){
if(msg == "")
return(e("Empty string"))
msg
}
pr("test.R") %>%
pr_run(port = 8000)
← Handling