Skip to content

Commit

Permalink
Add doc for Sliding Window (Count and Time) Breaker
Browse files Browse the repository at this point in the history
  • Loading branch information
tichon29 committed Oct 23, 2020
1 parent 41db75e commit 4865ed1
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 17 deletions.
28 changes: 27 additions & 1 deletion docs/api/module/sliding/count-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,30 @@ title: Mollitia - API - Module - Sliding Count Breaker

## Usage

TODO
The Circuit Breaker has 3 possible states:
* CLOSED
* OPEN
* HALF_OPEN

When the circuit is opened, all the requests are failing fast

When the circuit is half opened, a certain number of requests are authorrized. When this number is reached, the failure and slow call rate thresholds are checked to see if the circuit should be opened or closed.

When the circuit is closed, a sliding window is used to store the outcome of calls.
The count-based sliding window calculates the outcome of the last N calls, and decides if the circuit should be opened (if the failure or slow call rate thresholds are exceeded)
For example, if the count window size is 10, the circular array has always 10 measurements.

### Configuration

Here are the properties that you could set for your sliding count circuit breaker:

| Name | Type | Description | Default |
|:---------------------|:------------------------------|:----------------------------------------------------------------------------------------|:----------------|
| failureRateThreshold | `number` | Specifies the failure rate threshold in percentage | `50` |
| slowCallRateThreshold | `number` | Specifies the slow call rate threshold. A call is considered as slow when the call duration is greater thaan slowCallDurationThreshold | `100` |
| slowCallDurationThreshold | `number` | Specifies the duration (in ms) threshold above which calls are considered as slow | `60000 (ms)` |
| permittedNumberOfCallsInHalfOpenState | `number` | Specifies the number of permitted calls when the circuit is half open | `2` |
| halfOpenStateMaxDelay | `number` | Specifies the maximum wait (in ms) in Half Open State, before switching back to open. 0 deactivates this | `0` |
| slidingWindowSize | `number` | Specifies the maximum number of calls used to calculate failure and slow call rate percentages | `10` |
| minimumNumberOfCalls | `number` | Specifies the minimum number of calls rrequused to calculate failure and slow call rate percentages | `10` |
| openStateDelay | `number` | Specifies the time (in ms) the circuit stay opened before switching to half-open | `60000` |
28 changes: 27 additions & 1 deletion docs/api/module/sliding/time-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,30 @@ title: Mollitia - API - Module - Sliding Time Breaker

## Usage

TODO
The Circuit Breaker has 3 possible states:
* CLOSED
* OPEN
* HALF_OPEN

When the circuit is opened, all the requests are failing fast

When the circuit is half opened, a certain number of requests are authorrized. When this number is reached, the failure and slow call rate thresholds are checked to see if the circuit should be opened or closed.

When the circuit is closed, a sliding window is used to store the outcome of calls.
The time-based sliding window calculates the outcome of the last calls receiving during the last N milliseconds, and decides if the circuit should be opened (if the failure or slow call rate thresholds are exceeded)
For example, if the count window size is 10000, the circular array stores the requests that occurred during the last 10s (with a maximum of 1000 elements in the array)

### Configuration

Here are the properties that you could set for your sliding time circuit breaker:

| Name | Type | Description | Default |
|:---------------------|:------------------------------|:----------------------------------------------------------------------------------------|:----------------|
| failureRateThreshold | `number` | Specifies the failure rate threshold in percentage | `50` |
| slowCallRateThreshold | `number` | Specifies the slow call rate threshold. A call is considered as slow when the call duration is greater thaan slowCallDurationThreshold | `100` |
| slowCallDurationThreshold | `number` | Specifies the duration (in ms) threshold above which calls are considered as slow | `60000 (ms)` |
| permittedNumberOfCallsInHalfOpenState | `number` | Specifies the number of permitted calls when the circuit is half open | `2` |
| halfOpenStateMaxDelay | `number` | Specifies the maximum wait (in ms) in Half Open State, before switching back to open. 0 deactivates this | `0` |
| slidingWindowSize | `number` | Specifies the maximum number of calls used to calculate failure and slow call rate percentages | `60000 (ms)` |
| minimumNumberOfCalls | `number` | Specifies the minimum number of calls rrequused to calculate failure and slow call rate percentages | `10` |
| openStateDelay | `number` | Specifies the time (in ms) the circuit stay opened before switching to half-open | `60000 (ms)` |
3 changes: 1 addition & 2 deletions docs/vue/components/module/sliding/TimeBreakerModule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ export default {
slowCallRateThreshold: this.slowCallRateThreshold,
permittedNumberOfCallsInHalfOpenState: this.permittedNumberOfCallsInHalfOpenState,
openStateDelay: this.openStateDelay,
halfOpenStateMaxDelay: this.halfOpenStateMaxDelay,
slidingWindowSizeInMs: true
halfOpenStateMaxDelay: this.halfOpenStateMaxDelay
});
this.slidingTimeBreaker.on('stateChanged', this.onCircuitStateChanged);
}
Expand Down
13 changes: 11 additions & 2 deletions src/module/breaker/sliding/count-breaker.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { SlidingWindowBreaker, SlidingWindowRequestResult } from './index';
import { SlidingWindowBreaker, SlidingWindowBreakerOptions, SlidingWindowRequestResult } from './index';

export class SlidingCountBreaker extends SlidingWindowBreaker<SlidingWindowRequestResult> {

constructor(options?: SlidingWindowBreakerOptions) {
super(options);
this.slidingWindowSize = options?.slidingWindowSize || 10;
if (this.slidingWindowSize < this.minimumNumberOfCalls) {
this.slidingWindowSize = this.minimumNumberOfCalls;
}
}

public async executeInClosed<T> (promise: any, ...params: any[]): Promise<T> {
const {requestResult, response } = await this.executePromise(promise, ...params);
this.callsInClosedState.push(requestResult);
const nbCalls = this.callsInClosedState.length;
let nbCalls = this.callsInClosedState.length;
if (nbCalls >= this.minimumNumberOfCalls) {
while (nbCalls > this.slidingWindowSize) {
this.callsInClosedState.shift();
nbCalls--;
}
this.checkCallRatesClosed(this.open.bind(this));
}
Expand Down
5 changes: 1 addition & 4 deletions src/module/breaker/sliding/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ export abstract class SlidingWindowBreaker<T> extends Breaker {
super(options);
this.slidingWindowSize = options?.slidingWindowSize || 10;
this.minimumNumberOfCalls = options?.minimumNumberOfCalls || 10;
if (this.slidingWindowSize < this.minimumNumberOfCalls) {
this.slidingWindowSize = this.minimumNumberOfCalls;
}
this.failureRateThreshold = (options?.failureRateThreshold || 50);
this.slowCallDurationThreshold = options?.slowCallDurationThreshold || 60000;
this.slowCallRateThreshold = (options?.slowCallRateThreshold || 100);
this.permittedNumberOfCallsInHalfOpenState = options?.permittedNumberOfCallsInHalfOpenState || 10;
this.permittedNumberOfCallsInHalfOpenState = options?.permittedNumberOfCallsInHalfOpenState || 2;
this.nbCallsInHalfOpenedState = 0;
this.callsInHalfOpenedState = [];
this.callsInClosedState = [];
Expand Down
12 changes: 7 additions & 5 deletions src/module/breaker/sliding/time-breaker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ export interface SlidingTimeElem {
}

interface SlidingTimeBreakerOptions extends SlidingWindowBreakerOptions {
slidingWindowSizeInMs?: boolean
slidingWindowSizeInSeconds?: boolean
}

export class SlidingTimeBreaker extends SlidingWindowBreaker<SlidingTimeElem> {
private maxSize: number;
private slidingWindowSizeInSeconds: boolean;

constructor(options?: SlidingTimeBreakerOptions) {
super(options);
if (options?.slidingWindowSizeInMs) {
//Sliding window is in ms, no need to multiply by 1000
} else {
this.slidingWindowSize = options?.slidingWindowSize || 60;
this.slidingWindowSizeInSeconds = options?.slidingWindowSizeInSeconds || false;

if (this.slidingWindowSizeInSeconds) {
this.slidingWindowSize = this.slidingWindowSize * 1000;
}
this.maxSize = 1000;
Expand All @@ -41,7 +44,6 @@ export class SlidingTimeBreaker extends SlidingWindowBreaker<SlidingTimeElem> {

public async executeInClosed<T> (promise: any, ...params: any[]): Promise<T> {
const {requestResult, response } = await this.executePromise(promise, ...params);
//this.callsInClosedState = this.callsInClosedState.filter((elem) => (now - elem.timestamp) <= this.slidingWindowSize)
this.filterCalls();
this.callsInClosedState.push({result: requestResult, timestamp: (new Date()).getTime()});
if (this.callsInClosedState.length >= this.minimumNumberOfCalls) {
Expand Down
3 changes: 1 addition & 2 deletions test/mollitia.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@ describe('mollitia.ts', () => {
it('switch to Open when failure rate exceeded', async () => {
const slidingTimeBreaker = new Mollitia.SlidingTimeBreaker({
slidingWindowSize: 100,
slidingWindowSizeInMs: true,
minimumNumberOfCalls: 2,
failureRateThreshold: 60,
openStateDelay: 20,
Expand Down Expand Up @@ -370,7 +369,7 @@ describe('mollitia.ts', () => {
const slidingTimeCounter = new Mollitia.SlidingTimeBreaker({
failureRateThreshold: 50,
openStateDelay: 10,
slidingWindowSize: 1,
slidingWindowSize: 1000,
minimumNumberOfCalls: 2,
permittedNumberOfCallsInHalfOpenState: 1,
slowCallDurationThreshold: 100,
Expand Down

0 comments on commit 4865ed1

Please sign in to comment.