* Add Circuit Breaker to akka.pattern for general use. Circuit breaker implementation as described by Michael T. Nygard in Release It!. Fixes #1734

* Uses finite state machine for three states: Closed, Open, Half-Open
    * Closed state allows calls through, and on sequential failures exceeding the max# set - transitions to Open state. Intervening successes cause the failure count to reset to 0
    * Open state throws a CircuitOpenException on every call until the reset timeout is reached which causes a transition to Half-Open state
    * Half-Open state will allow the next single call through, if it succeeds - transition to Closed state, if it fails - transition back to Open state, starting the reset timer again
  * Allow configuration for the call and reset timeouts, as well as the maximum number of sequential failures before opening
  * Supports async or synchronous call protection
  * Callbacks are supported for state entry into Closed, Open, Half-Open.  These are run in the supplied execution context
  * Both thrown exceptions and calls exceeding max call time are considered failures
  * Uses akka scheduler for timer events
  * Integrated into File-Based durable mailbox
  * Sample documented for other durable mailboxes
This commit is contained in:
Brian Scully 2012-06-01 08:24:47 -04:00
parent 85c263e077
commit 6a415f0e9b
15 changed files with 1266 additions and 25 deletions

View file

@ -0,0 +1,43 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.circuitbreaker
//#imports1
import akka.util.duration._ // small d is important here
import akka.pattern.CircuitBreaker
import akka.actor.Actor
import akka.dispatch.Future
import akka.event.Logging
//#imports1
class CircuitBreakerDocSpec { }
//#circuit-breaker-initialization
class DangerousActor extends Actor {
val log = Logging(context.system, this)
implicit val executionContext = context.dispatcher
val breaker =
new CircuitBreaker(context.system.scheduler, 5, 10.seconds, 1.minute)
.onOpen(notifyMeOnOpen)
def notifyMeOnOpen =
log.warning("My CircuitBreaker is now open, and will not close for one minute")
//#circuit-breaker-initialization
//#circuit-breaker-usage
def dangerousCall: String = "This really isn't that dangerous of a call after all"
def receive = {
case "is my middle name" =>
sender ! breaker.withCircuitBreaker(Future(dangerousCall))
case "block for me" =>
sender ! breaker.withSyncCircuitBreaker(dangerousCall)
}
//#circuit-breaker-usage
}