@daiso-tech/core
Version:
The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.
128 lines • 4.97 kB
JavaScript
/**
* @module CircuitBreaker
*/
import {} from "../../../../backoff-policies/_module.js";
import { CIRCUIT_BREAKER_STATE, CLOSED_TRANSITIONS, HALF_OPEN_TRANSITIONS, } from "../../../../circuit-breaker/contracts/_module.js";
import { TimeSpan } from "../../../../time-span/implementations/_module.js";
import { callInvokable } from "../../../../utilities/_module.js";
/**
* @internal
*/
export class CircuitBreakerPolicy {
circuitBreakerPolicy;
constructor(circuitBreakerPolicy) {
this.circuitBreakerPolicy = circuitBreakerPolicy;
}
isMetricsEqual(metricsA, metricsB) {
return this.circuitBreakerPolicy.isEqual?.(metricsA, metricsB) ?? false;
}
isEqual(stateA, stateB) {
if (stateA.type === CIRCUIT_BREAKER_STATE.CLOSED &&
stateB.type === CIRCUIT_BREAKER_STATE.CLOSED) {
return this.isMetricsEqual(stateA.metrics, stateB.metrics);
}
if (stateA.type === CIRCUIT_BREAKER_STATE.OPEN &&
stateB.type === CIRCUIT_BREAKER_STATE.OPEN) {
return (stateA.attempt === stateB.attempt &&
stateA.startedAt === stateB.startedAt);
}
if (stateA.type === CIRCUIT_BREAKER_STATE.HALF_OPEN &&
stateB.type === CIRCUIT_BREAKER_STATE.HALF_OPEN) {
return (stateA.attempt === stateB.attempt &&
this.isMetricsEqual(stateA.metrics, stateB.metrics));
}
if (stateA.type === CIRCUIT_BREAKER_STATE.ISOLATED &&
stateB.type === CIRCUIT_BREAKER_STATE.ISOLATED) {
return true;
}
return false;
}
initialState() {
return {
type: CIRCUIT_BREAKER_STATE.CLOSED,
metrics: this.circuitBreakerPolicy.initialMetrics(),
};
}
whenClosed(currentState, currentDate) {
const transition = this.circuitBreakerPolicy.whenClosed(currentState.metrics, new Date(currentDate));
if (transition === CLOSED_TRANSITIONS.NONE) {
return currentState;
}
return {
type: CIRCUIT_BREAKER_STATE.OPEN,
attempt: 1,
startedAt: new Date(currentDate).getTime(),
};
}
whenOpened(currentState, settings) {
const waitTime = TimeSpan.fromTimeSpan(callInvokable(settings.backoffPolicy, currentState.attempt, null));
const endDate = waitTime.toEndDate(new Date(currentState.startedAt));
const isWaitTimeOver = endDate <= new Date(settings.currentDate);
if (isWaitTimeOver) {
return {
type: CIRCUIT_BREAKER_STATE.HALF_OPEN,
attempt: currentState.attempt,
metrics: this.circuitBreakerPolicy.initialMetrics(),
};
}
return currentState;
}
whenHalfOpened(currentState, currentDate) {
const transition = this.circuitBreakerPolicy.whenHalfOpened(currentState.metrics, new Date(currentDate));
if (transition === HALF_OPEN_TRANSITIONS.NONE) {
return currentState;
}
if (transition === HALF_OPEN_TRANSITIONS.TO_CLOSED) {
return {
type: CIRCUIT_BREAKER_STATE.CLOSED,
metrics: this.circuitBreakerPolicy.initialMetrics(),
};
}
return {
type: CIRCUIT_BREAKER_STATE.OPEN,
attempt: currentState.attempt + 1,
startedAt: new Date(currentDate).getTime(),
};
}
trackSuccessWhenClosed(currentState, currentDate) {
const newMetrics = this.circuitBreakerPolicy.trackSuccess(currentState, {
currentDate: new Date(currentDate),
initialMetrics: this.circuitBreakerPolicy.initialMetrics(),
});
return {
...currentState,
metrics: newMetrics,
};
}
trackFailureWhenClosed(currentState, currentDate) {
const newMetrics = this.circuitBreakerPolicy.trackFailure(currentState, {
currentDate: new Date(currentDate),
initialMetrics: this.circuitBreakerPolicy.initialMetrics(),
});
return {
...currentState,
metrics: newMetrics,
};
}
trackSuccessWhenHalfOpened(currentState, currentDate) {
const newMetrics = this.circuitBreakerPolicy.trackSuccess(currentState, {
currentDate: new Date(currentDate),
initialMetrics: this.circuitBreakerPolicy.initialMetrics(),
});
return {
...currentState,
metrics: newMetrics,
};
}
trackFailureWhenHalfOpened(currentState, currentDate) {
const newMetrics = this.circuitBreakerPolicy.trackFailure(currentState, {
currentDate: new Date(currentDate),
initialMetrics: this.circuitBreakerPolicy.initialMetrics(),
});
return {
...currentState,
metrics: newMetrics,
};
}
}
//# sourceMappingURL=circuit-breaker-policy.js.map