-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCircuitBreaker-manual-overrides.js
79 lines (72 loc) · 1.54 KB
/
CircuitBreaker-manual-overrides.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class CircuitBreaker {
constructor(request, options = {}) {
const defaults = {
failureThreshold: 3,
successThreshold: 2,
timeout: 6000
};
Object.assign(this, defaults, options, {
request,
state: "CLOSED",
failureCount: 0,
successCount: 0,
nextAttempt: Date.now()
});
}
async fire() {
if (this.state === "OPEN") {
if (this.nextAttempt <= Date.now()) {
this.state = "HALF";
} else {
throw new Error("Breaker is OPEN");
}
}
try {
const response = await this.request();
return this.success(response);
} catch (err) {
return this.fail(err);
}
}
success(response) {
if (this.state === "HALF") {
this.successCount++;
if (this.successCount > this.successThreshold) {
this.close();
}
}
this.failureCount = 0;
this.status("Success");
return response;
}
fail(err) {
this.failureCount++;
if (this.failureCount >= this.failureThreshold) {
this.open();
}
this.status("Failure");
return err;
}
open() {
this.state = "OPEN";
this.nextAttempt = Date.now() + this.timeout;
}
close() {
this.successCount = 0;
this.failureCount = 0;
this.state = "CLOSED";
}
half() {
this.state = "HALF";
}
status(action) {
console.table({
Action: action,
Timestamp: Date.now(),
Successes: this.successCount,
Failures: this.failureCount,
"Next State": this.state
});
}
}
module.exports = CircuitBreaker;