The Circuit Breaker design pattern is used to increase application stability, improve response times and prevent the application from making constant failing requests. This library provides the tools needed to bring Circuit Breaker logic to your Swift applications.
The latest version of CircuitBreaker works with the 4.1.2
and newer version of the Swift binaries. You can download this version of the Swift binaries by following this link.
Add CircuitBreaker
to the dependencies within your application's Package.swift
file. Substitute "x.x.x"
with the latest CircuitBreaker
release.
.package(url: "https://github.com/Kitura-Next/CircuitBreaker.git", from: "x.x.x")
Add CircuitBreaker
to your target's dependencies:
.target(name: "example", dependencies: ["CircuitBreaker"]),
Import the package inside your application:
import CircuitBreaker
The CircuitBreaker state is based on timeouts and user defined failures (quite useful when the function you are circuit breaking makes an asynchronous call). To use the CircuitBreaker in your application code you need to do the following:
(BreakerError, (fallbackArg1, fallbackArg2, ...)) -> Void
:func myFallback(err: BreakerError, msg: String) {
// The fallback will be called if one of the below occurs:
// 1. The request does not return before the specified timeout
// 2. CircuitBreaker is currently in Open state and set to fail fast.
// 3. There was an error in the user's called context function (networking error, etc.)
Log.verbose("Error: \(err)")
Log.verbose("Message: \(msg)")
}
extension BreakerError {
public static let encodingURLError = BreakerError(reason: "URL could not be created")
public static let networkingError = BreakerError(reason: "There was an error, while sending the request")
public static let jsonDecodingError = BreakerError(reason: "Could not decode result into JSON")
}
Invocation
object as its parameter. An instance of the Invocation
class states:
func myContextFunction(invocation: Invocation<(String), String>) {
let requestParam = invocation.commandArgs
// Create HTTP request
guard let url = URL(string: "http://myserver.net/path/\(requestParam)") else {
// Something went wrong
invocation.notifyFailure(error: .encodingURLError)
return
}
var req = URLRequest(url: url)
req.httpMethod = "GET"
let session = URLSession.shared
// Perform the request
session.dataTask(with: req) { result, res, err in
guard let result = result else {
// Failed getting a result from the server
invocation.notifyFailure(error: .networkingError)
return
}
// Convert results to a JSON object
guard let json = (try? JSONSerialization.jsonObject(with: result, options: [])) as? [String: Any] else {
invocation.notifyFailure(error: .jsonDecodingError)
return
}
// Process JSON data
invocation.notifySuccess()
}.resume()
}
let breaker = CircuitBreaker(name: "Circuit1", command: myContextFunction, fallback: myFallback)
run()
method. You should pass the corresponding arguments for the context command and fallback closures. In this sample, myContextFunction
takes a string as its parameter while myFallback
takes a string as its second parameter:let requestParam: String = "myRequestParams"
breaker.run(commandArgs: requestParam, fallbackArgs: "Something went wrong.")
extension BreakerError {
public static let encodingURLError = BreakerError(reason: "URL could not be created")
public static let networkingError = BreakerError(reason: "There was an error, while sending the request")
public static let jsonDecodingError = BreakerError(reason: "Could not decode result into JSON")
}
func myFallback(err: BreakerError, msg: String) {
// The fallback will be called if one of the below occurs:
// 1. The request does not return before the specified timeout
// 2. CircuitBreaker is currently in Open state and set to fail fast.
// 3. There was an error in the user's called context function (networking error, etc.)
Log.verbose("Error: \(err)")
Log.verbose("Message: \(msg)")
}
func myContextFunction(invocation: Invocation<(String), String>) {
let requestParam = invocation.commandArgs
// Create HTTP request
guard let url = URL(string: "http://mysever.net/path/\(requestParam)") else {
// Something went wrong...
invocation.notifyFailure(error: .encodingURLError)
}
var req = URLRequest(url: url)
req.httpMethod = "GET"
let session = URLSession.shared
// Perform Request
session.dataTask(with: req) { result, res, err in
guard let result = result else {
// Failed getting a result from the server
invocation.notifyFailure(error: .networkingError)
return
}
// Convert results to a JSON object
guard let json = (try? JSONSerialization.jsonObject(with: result, options: [])) as? [String: Any] else {
invocation.notifyFailure(error: .jsonDecodingError)
return
}
// Process JSON data
invocation.notifySuccess()
}.resume()
}
let breaker = CircuitBreaker(name: "Circuit1", command: myContextFunction, fallback: myFallback)
let requestParam: String = "myRequestParams"
breaker.run(commandArgs: requestParam, fallbackArgs: "Something went wrong.")
The following statistics will be tracked for the CircuitBreaker instance:
The example code below shows how to log a snapshot of the statistics and how to create a Hystrix compliant snapshot.
// Create CircuitBreaker
let breaker = CircuitBreaker(name: "Circuit1", command: myFunction, fallback: myFallback)
// Invoke breaker call
breaker.run(commandArgs: (a: 10, b: 20), fallbackArgs: "Something went wrong.")
// Log statistics snapshot
breaker.logSnapshot()
// Hystrix compliant snapshot
let snapshot = breaker.snapshot
The CircuitBreaker library provides an interface for observing new CircuitBreaker instances in order to register and track statistics changes. In the initialization of a CircuitBreaker instance, the linked monitors are notified of its instantiation allowing them to begin tracking the instance's statistics. The CircuitBreaker instance exposes a Hystrix compliant statistics snapshot to the monitor which can then be processed accordingly. See the API documentation for more information.
For more information visit our API reference.
We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!
This Swift package is licensed under Apache 2.0. Full license text is available in LICENSE.
link |
Stars: 0 |
Last commit: 3 years ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics