Reputation: 20182
I find the Success case is frequently buried in a match of many errors and one success. Is there another way to write this more cleanly such that sucess stands out perhaps by having all errors in a partial function? Or perhaps, there is another way to write it but just cleaner. I am in general just looking for other ideas/solutions that could be done.
results.responseCode match {
case Success =>
// TODO make this less smelly. can results.results be None?
val searchResults = results.results.get.results
SomeService.getUsersFromThriftResults(
userRepo,
searchResults,
Seq(WithCounts)) map { userResults =>
val renderableStatuses = getStatuses(searchResults, userResults.userMap)
new JsonAction(transformedQuery, renderableStatuses)
}
case ErrorInvalidQuery =>
throw new SomeBadRequestException("invalid query")
case ErrorOverCapacity |
ErrorTimeout =>
throw new SomeServiceUnavailableException("service unavailable")
//TODO: take care of these errors differently
// case ErrorInvalidWorkflow |
// ErrorBackendFailure |
// ErrorEventNotFound |
// PartialSuccess |
case _ =>
throw new SomeApplicationException("internal server error")
}
Upvotes: 0
Views: 464
Reputation: 37431
You can chain partial functions with orElse
.
Something like
type ResponseCode = Int // This would be the type of the results.responseCode.
type RespHandler = PartialFunction[ResponseCode, JsonAction]
val invalidQuery: RespHandler =
{ case ErrorInvalidQuery => ... }
val overCapacity: RespHandler =
{ case ErrorOverCapacity => ... }
results.responseCode match {
case Success => ...
} orElse invalidQuery orElse overCapacity orElse ...
You can see more about this at this blog post: Chaining Partial Functions with orElse
Edit: This doesn't work as written, you'll need to compose the handling and then apply
it (eg (success orElse invalidQuery ..)(results.getResponseCode)
).
A better solution is to change it to return a Try[ResponseCode]
and handle the exception in a Failure
match block.
Upvotes: 3
Reputation: 4053
You could try Try[A].
Example from documentation:
import scala.util.{Try, Success, Failure}
def divide: Try[Int] = {
val dividend = Try(Console.readLine("Enter an Int that you'd like to divide:\n").toInt)
val divisor = Try(Console.readLine("Enter an Int that you'd like to divide by:\n").toInt)
val problem = dividend.flatMap(x => divisor.map(y => x/y))
problem match {
case Success(v) =>
println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
Success(v)
case Failure(e) =>
println("You must've divided by zero or entered something that's not an Int. Try again!")
println("Info from the exception: " + e.getMessage)
divide
}
}
Upvotes: 2
Reputation: 4060
You could convert result to Either[ResponseCode, Content]
def codeToEither(result: Result): Either[ResponseCode, Content] =
result.responseCode match {
case Success => Right(result.results.get.results)
case _ => Left(result.responseCode)
}
And then fold
over it
codeToEither(result).fold(
errorCode => ... ,
content => ...
)
Or convert result to Either[Exception, Content]
in the same way, if you like.
Upvotes: 1
Reputation: 8591
You should consider using Either[Throwable, A] to represent the result type.
http://tersesystems.com/2012/12/27/error-handling-in-scala/
Upvotes: 1