Circuit breaker
npm install @da440dil/cbrtypescript
import http from 'node:http';
import { once } from 'node:events';
import { setTimeout } from 'node:timers/promises';
import { fixedWindow, Breakable } from '@da440dil/cbr';
// Create circuit which uses "Fixed Window" algorithm to store counters for 10s,
// switches from "Closed" to "Open" state on first error, from "Open" to "HalfOpen" state after 100ms,
// from "HalfOpen" to "Closed" state on first success.
const circuit = fixedWindow({ windowSize: 10000, resetTimeout: 100 });
circuit.on('state', (state) => {
console.log(STATE: ${state});
});
class Client {
// Decorate class method with circuit breaker logic.
@Breakable(circuit)
public async get(): Promise {
const res = await fetch('http://localhost:3000');
if (res.status !== 200) {
throw new Error( Failed with status ${res.status});
}
return res.text();
}
}
async function main() {
let x = 0;
const server = http.createServer((_, res) => {
// { 0 => 200, 1 => 418, 2 => 200, ... => 418 }
res.writeHead(x > 2 || x % 2 ? 418 : 200).end({ x: ${x++} });
});
server.listen(3000);
await once(server, 'listening');
const client = new Client();
for (let i = 0; i < 3; i++) {
try {
const data = await client.get();
console.log(DATA: ${data});
} catch (err) {
console.log(ERROR: ${err});
}
}
console.log(TIMEOUT ${circuit.resetTimeout}ms);
await setTimeout(circuit.resetTimeout);
const data = await client.get();
console.log(DATA: ${data});
// Output:
// DATA: { x: 0 }
// STATE: 1
// ERROR: Error: Failed with status 418
// ERROR: CircuitError: Circuit broken
// TIMEOUT 100ms
// STATE: 2
// STATE: 0
// DATA: { x: 2 }
server.close();
await once(server, 'close');
}
main().catch(console.error);
`
`
npm run file examples/decorator.ts
``