@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.
131 lines (125 loc) • 5.3 kB
JavaScript
/**
* @module CircuitBreaker
*/
import {} from "ioredis";
import { BACKOFFS, resolveBackoffSettingsEnum, serializeBackoffSettingsEnum, } from "../../../../backoff-policies/_module.js";
import { CIRCUIT_BREAKER_STATE, } from "../../../../circuit-breaker/contracts/_module.js";
import {} from "../../../../circuit-breaker/implementations/adapters/database-circuit-breaker-adapter/circuit-breaker-policy.js";
import { circuitBreakerFactoryLua } from "../../../../circuit-breaker/implementations/adapters/redis-circuit-breaker-adapter/lua/_module.js";
import { BREAKER_POLICIES, resolveCircuitBreakerPolicySettings, serializeCircuitBreakerPolicySettingsEnum, } from "../../../../circuit-breaker/implementations/policies/_module.js";
/**
* IMPORT_PATH: `"@daiso-tech/core/circuit-breaker/redis-circuit-breaker-adapter"`
* @group Adapters
*/
export class RedisCircuitBreakerAdapter {
backoff;
policy;
database;
/**
* @example
* ```ts
* import { RedisCircuitBreakerAdapter } from "@daiso-tech/core/circuit-breaker/redis-circuit-breaker-adapter";
* import Redis from "ioredis";
*
* const database = new Redis("YOUR_REDIS_CONNECTION_STRING");
* const circuitBreakerAdapter = new RedisCircuitBreakerAdapter({
* database
* });
* ```
*/
constructor(settings) {
const { database, backoff = {
type: BACKOFFS.EXPONENTIAL,
}, policy = {
type: BREAKER_POLICIES.CONSECUTIVE,
}, } = settings;
this.database = database;
this.backoff = resolveBackoffSettingsEnum(backoff);
this.policy = resolveCircuitBreakerPolicySettings(policy);
this.initUpdateStateCommmand();
this.initTrackFailureCommmand();
this.initTrackSuccessCommmand();
}
initUpdateStateCommmand() {
if (typeof this.database.daiso_circuit_breaker_update_state ===
"function") {
return;
}
this.database.defineCommand("daiso_circuit_breaker_update_state", {
numberOfKeys: 1,
lua: `
${circuitBreakerFactoryLua}
local key = KEYS[1];
local backoffSettings = cjson.decode(ARGV[1]);
local policySettings = cjson.decode(ARGV[2]);
local currentDate = tonumber(ARGV[3]);
local circuitBreaker = circuitBreakerFactory(backoffSettings, policySettings, currentDate)
local transition = circuitBreaker.updateState(key)
return cjson.encode(transition)
`,
});
}
initTrackFailureCommmand() {
if (typeof this.database.daiso_circuit_breaker_track_failure ===
"function") {
return;
}
this.database.defineCommand("daiso_circuit_breaker_track_failure", {
numberOfKeys: 1,
lua: `
${circuitBreakerFactoryLua}
local key = KEYS[1];
local backoffSettings = cjson.decode(ARGV[1]);
local policySettings = cjson.decode(ARGV[2]);
local currentDate = tonumber(ARGV[3]);
local circuitBreaker = circuitBreakerFactory(backoffSettings, policySettings, currentDate)
circuitBreaker.trackFailure(key)
`,
});
}
initTrackSuccessCommmand() {
if (typeof this.database.daiso_circuit_breaker_track_success ===
"function") {
return;
}
this.database.defineCommand("daiso_circuit_breaker_track_success", {
numberOfKeys: 1,
lua: `
${circuitBreakerFactoryLua}
local key = KEYS[1];
local backoffSettings = cjson.decode(ARGV[1]);
local policySettings = cjson.decode(ARGV[2]);
local currentDate = tonumber(ARGV[3]);
local circuitBreaker = circuitBreakerFactory(backoffSettings, policySettings, currentDate)
circuitBreaker.trackSuccess(key)
`,
});
}
async getState(key) {
const value = await this.database.get(key);
if (value === null) {
return CIRCUIT_BREAKER_STATE.CLOSED;
}
const state = JSON.parse(value);
return state.type;
}
async updateState(key) {
const value = await this.database.daiso_circuit_breaker_update_state(key, JSON.stringify(serializeBackoffSettingsEnum(this.backoff)), JSON.stringify(serializeCircuitBreakerPolicySettingsEnum(this.policy)), Date.now());
return JSON.parse(value);
}
async isolate(key) {
await this.database.set(key, JSON.stringify({
type: CIRCUIT_BREAKER_STATE.ISOLATED,
}));
}
async trackFailure(key) {
await this.database.daiso_circuit_breaker_track_failure(key, JSON.stringify(serializeBackoffSettingsEnum(this.backoff)), JSON.stringify(serializeCircuitBreakerPolicySettingsEnum(this.policy)), Date.now());
}
async trackSuccess(key) {
await this.database.daiso_circuit_breaker_track_success(key, JSON.stringify(serializeBackoffSettingsEnum(this.backoff)), JSON.stringify(serializeCircuitBreakerPolicySettingsEnum(this.policy)), Date.now());
}
async reset(key) {
await this.database.del(key);
}
}
//# sourceMappingURL=redis-circuit-breaker-adapter.js.map