Most of my work these days has been around backend systems written in Scala. Whenever I’m working on a project, one of the abstractions I often end using are services.

In many cases, the methods on my services return a Future. A Future in Scala is a way of representing asynchronous computations. They are handled in a non-blocking way and act as a placeholders for values that may not yet exist. Consider, for instance, values obtained when communicating with downstream systems (HTTP calls, repositories, etc). On those same cases, though, a series of other concerns start to manifest. For example, should I retry a failed call? And if doing so, ain’t I actually stressing an already unhealthy downstream system?

On the book Release It!, the author introduces the concept of circuit breakers as a software pattern to handle these precise problems. The idea is simple: if I had too many failures in a short period while doing a specific operation, I start to prevent further calls to that operation to be made, breaking my circuit and make it open. New calls would then fail, with an exception for instance, instead of doing the original call. After a few moments, I then gradually start to attempt calling it, and if they now seem to be working correctly, I move back to the closed state and let all requests to be forwarded.

A great implementation of this pattern is Hystrix. Akka also happens to have their own implementation.

While looking for a generic way to put those in use, my attempt was to do it on a way that would not pollute existing code with this logic. To be honest, I don’t want my service implementation to worry so much about it, as their focus should be about doing the things that they are supposed to do (communicate with other systems, etc).

That made me into creating a new library: autobreaker. autobreaker is a convenience library that wraps your objects and protects all methods returning a Future with a circuit breaker. It also allows you to define rules of when to retry calls. It is based on atmos and Akka’s circuit breaker, using Java’s Proxy to intercept method calls.

With autobreaker, given a service implementation, you can simply do the following in order to start using circuit breakers:

import com.unstablebuild.autobreaker._

val service: MyService = new MyDownstreamService
val serviceWithCircuitBreaker: MyService = AutoBreaker.proxy(service)

serviceWithCircuitBreaker.doSomething("hello")

The usage of your object doesn’t change at all, but given enough failing calls, they would start to fail fast and avoid calling the original code. Instead, calls to a open circuit would return a custom exception and log the problem:

// [warn] e.c.CircuitBreakerProxy - Attempt 1 of operation interrupted: akka.pattern.CircuitBreakerOpenException: Circuit Breaker is open; calls are failing fast
// akka.pattern.CircuitBreakerOpenException: Circuit Breaker is open; calls are failing fast

autobreaker also allows you to decide what exception types should be considered failures. This becomes handy when you use exceptions to represent any sort of problem that deviates from your happy path, i.e. validation problems. This adapts quite well with Futures, since they provide several features to handle exceptions. It is also very nice to rescue from failures, or map failures to, let’s say, HTTP status codes using pattern matching. For instance, in a lot of my projects I create a common interface to represent these failures, and make my errors extend them:

sealed trait ApplicationError extends Exception with NoStackTrace
case object InexistentId extends ApplicationError
case object InvalidName extends ApplicationError
case object UnallowedOperation extends ApplicationError

val statusCode = error match {
  case InexistentId | InvalidName => 400
  case UnallowedOperation => 403
}

Therefore, you could define that an InvalidName is not an error that should cause a circuit breaker to open.

If you liked the idea, I invite you to take a better look on the project’s documentation.