finagle / finagle/roc

Preferred Roc Error Handling?

Open
#21 1 comment 0 reactions 0 assignees View on GitHub
Discussion
Dominant language
Scala
Stars
55
Forks
7
PR merge metrics
No merged PRs in 30d

Description

## Problem

What is the appropriate way to handle errors in Roc? There are several important factors weighing in on this decision
1. We are not bound by JDBC style of error handling.
2. Postgresql has explicit documentation around "error classes" that allows us to model a great many Server errors without the need to create `Exceptions`
3. From point 2., there are [278](http://www.postgresql.org/docs/current/static/errcodes-appendix.html) explicit types of errors Postgresql can emit, and [41](http://www.postgresql.org/docs/current/static/errcodes-appendix.html) "error classes" that these 278 fall into.
4. From point 3., these 41 Error Class codes can be further classified as "Error", "Fatal", "Panic", "Warning", "Notice", "Debug", "Info", "Log" to denote the expected action of a client.
5. "Adhere to the style of the original" suggests that we should not stray too far from the `Twitter.Future.exception` style of handling.
6. The `Result` type is more or less undefined at this point - currently it just holds some information returned from the DB, but this isn't firm in the slightest and I expect it to change dramatically as the code continues to reveal itself.

Currently, we are modeling any Errors that happen in the client ( for example, decoding failures ) as Failures, and any Exceptions that occur on the postgresql side as PostgresqlErrors

``` scala
abstract class Failure extends Exception // Client side problems
abstract class PostgresqlError // Server side problems
```
## Possible Solutions
### The "kill -9"

Perhaps the easiest of these, we create a simple type to model any error from a Postgresql database. Upon receipt of any error, we immediately close the connection and return a

``` scala
case class PostgresqlError extends Exception
Future.exception(new PostgresqlError())
```
### The "all. the. errors." approach

``` scala
sealed abstract class PostgresqlError // does NOT extend Exception
case class UndefinedColumn extends PostgresqlError
```

Under this approach, we explicitly model each Postgresql Error type. As the errors are a closed set ( i.e., there is a well defined set of errors and a well defined behavior if, for some reason, an error is returned that does not appear in this set), this is certainly a possibility. The connection would not be closed, and the `Result` type would have a way to model a possible error ( perhaps as a disjunction? ).

However, the enormous number of error types makes this challenging and error prone for any user.
### The "adhere to JDBC style" approach

In this scenario, we would map Postgreql Errors to their corresponding JDBC Exceptions, and then simply bail out in the client code:

``` scala
// some decoding has occurred above
val error = InvalidColumnReference
Future.exception(new java.sql.SQLException(error))
```
### The "let's just cut the baby in half" approach

In this scenario, we would create Error Types based off the severity level. Errors that do not affect the connection state would simply be errors, while errors that do affect the connection state would also be Exceptions, i.e.

``` scala
sealed abstract class PostgresqlError
case class Error extends PostgresqlError // example, "no table named FOO exists"
case class Fatal extends PostgresqlError with Exception // example, admin shutdown initiated
case class Panic extends PostgresqlError with Exception // example, OOM
case class Debug extends PostgresqlError
```

Non-exception types would be returned as the Result type (still not sure how though), while any connection closing errors would close the connection, and then bail out via

``` scala
Future.exception(new Fatal())
```

Thoughts on this? I'm kind of torn between the "shove everything into a Future.exception" and "model all error types".

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reviewing the current Failure, PostgresqlError, and Result types described in the issue, then trace how client decoding failures and PostgreSQL server errors reach Future.exception. Done means the project has an agreed error model, including connection behavior and Result representation, rather than another unresolved design discussion.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, scala
Domain
backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.