Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Kotlin Multiplatform fault-tolerance library with Ktor integration

License

kresil/kresil

Repository files navigation

Kresil - Kotlin Resilience Library

Kresil is a Kotlin Multiplatform library for fault-tolerance, inspired by Resilience4j for Java and Polly for .NET. The library offers methods to enhance operations with resilience mechanisms in a functional style, using higher-order functions (decorators) while providing a concise API. Additionally, Kresil offers extensions for Ktor as plugins.

Resilience Mechanisms

Note

The symbol 🚧 means that the mechanism is under development.

Relevant Modules

Retry

A Retry is a reactive resilience mechanism that can be used to retry an operation when it fails and the failure is a transient (temporary) fault. Operations can be decorated and executed on demand. A retry mechanism is initialized with a configuration that, through pre-configured policies, define its behaviour.

State Machine

The retry mechanism implements the following state machine:

                   +------------------+  retried once   +---------+
+-----------+ ---> | Returns Normally | --------------> | Success |
| Operation |      +------------------+                 +---------+
|  Called   |      +-------+      +----------+
+-----------+ ---> | Fails | ---> | Consults |
      ^            +-------+      | Policies |
      |                           +----------+
      |                                |
  +-------+      can use retry         |
  | Retry | <--------------------------|
  +-------+                            |   expected
                                       |   failure    +-------+
                                       |------------> | Error |
                                       |              +-------+
                    +---------+        |
                    | Ignored | <------|
                    |  Error  |
                    +---------+

Usage

// use predefined retry policies
val defaultRetry = Retry()

// use custom policies
val retry = Retry(
    retryConfig {
        maxAttempts = 5 // initial call + 4 retries
        retryIf { it is NetworkError }
        retryOnResult { it is "success" }
        exponentialDelay(initialDelay = 500L.milliseconds, multiplier = 1.0, maxDelay = 1.minutes, randomizationFactor = 0.1)
        // customDelay { attempt, context -> ... }
        // exceptionHandler { exception -> ... }
    }
)

// execute a supplier
retry.executeSupplier {
    // operation
}

// execute a supplier with context
retry.executeCtxSupplier { ctx ->
    // operation
}

// decorate a supplier
val decoratedSupplier = retry.decorateSupplier {
    // operation
}
// and call it later
val result = decoratedSupplier()

// listen to specific events
retry.onRetry { event ->
    // action
}

// listen to all events
retry.onEvent { event ->
    // action
}

// cancel all listeners
retry.cancelListeners()

Circuit Breaker

The Circuit Breaker is a reactive resilience mechanism that can be used to protect a system component from overloading or failing. By monitoring the health of the system, the circuit breaker can short-circuit execution requests when it detects that the system component is not behaving as expected. After a configurable timeout, the circuit breaker allows a limited number of test requests to pass through to see if the system has recovered. Depending on the test results, the circuit breaker can resume normal operation or continue to short-circuit requests. A circuit breaker is initialized with a configuration that, through pre-configured policies, define its behaviour.

State Machine

The circuit breaker implements the following state machine:

             failure rate exceeds
 +--------+  or equals threshold   +------+
 | Closed | ---------------------> | Open |
 +--------+                        +------+
     ^                               |  ^
     |                         after |  |  failure rate
     |                       timeout |  |  exceeds or
     |                               |  |  equals threshold
     |       failure rate            v  |
     |       below threshold     +-----------+
     |-------------------------- | Half-Open |
                                 +-----------+
  • In the Closed state, the circuit breaker allows calls to execute the underlying operation, while recording the success or failure of these calls. When the failure rate exceeds a (configurable) threshold, the circuit breaker transitions to the Open state.
  • In the Open state, the circuit breaker rejects all received calls for a (configurable) amount of time and then transitions to the HalfOpen state.
  • In the HalfOpen state, the circuit breaker allows a (configurable) number of calls to test if the underlying operation is still failing. After all calls have been attempted, the circuit breaker transitions back to the Open state if newly calculated failure rate exceeds or equals the threshold; otherwise, it transitions to the Closed state.

Usage

// use predefined policies
val defaultCircuitBreaker = CircuitBreaker()

// use custom policies
val circuitBreaker = CircuitBreaker(
    circuitBreakerConfig {
        failureRateThreshold = 0.5 // 50%
        recordResultPredicate { it is "success" }
        recordExceptionPredicate { it is NetworkError }
        exponentialDelayInOpenState(initialDelay = 30.seconds, multiplier = 2.0, maxDelay = 10.minutes)
        slidingWindow(size = 5, minimumThroughput = 2, type = COUNT_BASED)
    }
)

// get the current state of the circuit breaker
val observedState = circuitBreaker.currentState()

// wire the circuit breaker
circuitBreaker.wire()

// execute an operation under the circuit breaker
val result = circuitBreaker.executeOperation {
    // operation
}

// listen to specific events
circuitBreaker.onCallNotPermitted { event ->
    // action
}

// listen to all events
circuitBreaker.onEvent { event ->
    // action
}

// cancel all registered listeners
circuitBreaker.cancelListeners()

// manually:
// - override the circuit breaker state
circuitBreaker.transitionToOpen()
// - reset the circuit breaker
circuitBreaker.reset()
// - record an operation success
circuitBreaker.recordSuccess()
// - record an operation failure
circuitBreaker.recordFailure()

Rate Limiter

The Rate Limiter is a proactive resilience mechanism that can be used to limit the number of requests that can be made to a system component, thereby controlling the consumption of resources and protecting the system from overloading. A rate limiter is initialized with a configuration that, through pre-configured policies, defines its behaviour.

Releases

No releases published

Packages

No packages published

Languages