Question

In regard to potential runtime failures, like database queries, it seems that one must use some form of Either[String, Option[T]] in order to accurately capture the following outcomes:

  1. Some (record(s) found)
  2. None (no record(s) found)
  3. SQL Exception

Option simply does not have enough options.

I guess I need to dive into scalaz, but for now it's straight Either, unless I'm missing something in the above.

Have boxed myself into a corner with my DAO implementation, only employing Either for write operations, but am now seeing that some Either writes depend on Option reads (e.g. checking if email exists on new user signup), which is a majorly bad gamble to make.

Before I go all-in on Either, does anyone have alternate solutions for how to handle the runtime trifecta of success/fail/exception?

Was it helpful?

Solution

Use Option[T] for the cases records found and no records found and throw an exception in the case of SQLException.

Just wrap the exception inside your own exception type, like PersistenceException so that you don't have a leaky abstraction.

We do it like this because we can't and don't want to recover from unexpected database exceptions. The exception gets caught on the top level and our web service returns a 500 Internal server error in such case.

In cases where we want to recover we use Validation from scalaz, which is much like Lift's Box.

OTHER TIPS

Try Box from the fantastic lift framework. It provides exactly what you want.

See this wiki (and the links at the top) for details. Fortunately lift project is well modulized, the only dependency to use Box is net.lift-web % lift-common

Here's my revised approach

Preserve Either returning query write operations (useful for transactional blocks where we want to rollback on for comprehension Left outcome).

For Option returning query reads, however, rather than swallowing the exception with None (and logging it), I have created a 500 error screen, letting the exception bubble up.

Why not just work with Either result type by default when working with runtime failures like query Exceptions? Option[T] reads are a bit more convenient to work with vs Either[Why-Fail, Option[T]], which you have to fold/map through to get at T. Leaving Either to write operations simplifies things (all the more so given that's how the application is currently setup, no refactoring required ;-))

The only other change required is for AJAX requests. Rather than displaying the entire 500 error page response in the AJAX status div container, we check for the status type and display 500 error message accordingly.

if(data.status == 500) 
  $('#status > div').html("an error occurred, please try again")

Could probably do an isAjax check server-side prior to sending the response; in which case I can send back only status + message rather than the error page itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top