redeye-breaker 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -14
- package/dist/circuit-breaker.d.ts +64 -2
- package/dist/circuit-breaker.d.ts.map +1 -1
- package/dist/circuit-breaker.js +142 -19
- package/dist/circuit-breaker.js.map +1 -1
- package/dist/store.d.ts +25 -5
- package/dist/store.d.ts.map +1 -1
- package/dist/stores/redis-store.d.ts +19 -5
- package/dist/stores/redis-store.d.ts.map +1 -1
- package/dist/stores/redis-store.js +36 -7
- package/dist/stores/redis-store.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,6 +39,15 @@ const result = await breaker.execute('payment-gateway', () => callPaymentGateway
|
|
|
39
39
|
|
|
40
40
|
Local mode gets real half-open (single in-flight trial) and backoff+jitter too — it's single-process, so there's no atomicity concern to begin with.
|
|
41
41
|
|
|
42
|
+
### Local mode vs. distributed mode: which do you need?
|
|
43
|
+
|
|
44
|
+
Local mode is not the "lesser" option — for a lot of services, N independent per-instance breakers is the right answer, not a compromise:
|
|
45
|
+
|
|
46
|
+
- **Use local mode** when each instance tripping independently is fine, or even preferable: instances see meaningfully different traffic, the dependency is instance-local anyway (a sidecar, a per-instance cache), or you'd rather each instance protect itself than take on a new piece of shared infrastructure (the store) that can itself fail. Zero dependencies, zero added latency per call, nothing extra to operate.
|
|
47
|
+
- **Use distributed mode** when a failure burst against a *shared* downstream dependency should trip the breaker for the whole fleet at once — e.g. a payment gateway or third-party API, where 5 of 6 instances continuing to hammer a dependency the 6th just found dead is actively harmful (wasted capacity, a worse incident, a slower recovery signal). This costs something real in return: a store round trip on every gated decision (see [item 1](#whats-still-a-fundamental-tradeoff-not-a-bug) below), and a new dependency whose own outages now shape the breaker's behavior (see [Total coordination-layer outage](#total-coordination-layer-outage-the-store-itself-is-down)).
|
|
48
|
+
|
|
49
|
+
If you're not sure, start local — it's strictly cheaper, and nothing about switching to distributed mode later changes your call sites.
|
|
50
|
+
|
|
42
51
|
### Two tripping strategies
|
|
43
52
|
|
|
44
53
|
```ts
|
|
@@ -91,9 +100,11 @@ await breaker.execute('payment-gateway', () => callPaymentGateway());
|
|
|
91
100
|
|
|
92
101
|
Every process pointed at the same Redis instance (and using the same operation name / key prefix) shares breaker state, with atomic counting and single-trial recovery.
|
|
93
102
|
|
|
103
|
+
`RedisStore` stores state under `{keyPrefix}circuit_breaker:{operation}`, plus `{keyPrefix}circuit_breaker:{operation}:trial` while a half-open trial is in flight. `keyPrefix` defaults to `''` (no prefix) — set one (as above) if you share a Redis instance/DB across services and want your keys namespaced.
|
|
104
|
+
|
|
94
105
|
### Bring your own store
|
|
95
106
|
|
|
96
|
-
`RedisStore` implements a `Store` interface with two required methods and
|
|
107
|
+
`RedisStore` implements a `Store` interface with two required methods and four *optional* ones:
|
|
97
108
|
|
|
98
109
|
```ts
|
|
99
110
|
export interface Store {
|
|
@@ -106,20 +117,22 @@ export interface Store {
|
|
|
106
117
|
// one-time warning telling you exactly what's degraded.
|
|
107
118
|
recordFailureAtomic?(key: string, opts: { ttlSeconds: number; failureThreshold: number; now: number }): Promise<CircuitBreakerState>;
|
|
108
119
|
recordOutcomeAtomic?(key: string, opts: { success: boolean; decay: number; minimumCalls: number; errorRateThreshold: number; ttlSeconds: number; now: number }): Promise<CircuitBreakerState & { openedNow: boolean }>;
|
|
109
|
-
claimTrial?(key: string, ttlSeconds: number): Promise<
|
|
120
|
+
claimTrial?(key: string, ttlSeconds: number): Promise<string | null>;
|
|
121
|
+
releaseTrial?(key: string, token: string): Promise<void>;
|
|
110
122
|
}
|
|
111
123
|
```
|
|
112
124
|
|
|
113
125
|
- `recordFailureAtomic` (`strategy: 'consecutive'`) should increment the failure count and decide `isOpen` in one atomic round trip (a Lua script in Redis, a conditional update in DynamoDB, etc.).
|
|
114
126
|
- `recordOutcomeAtomic` (`strategy: 'errorRate'`) should fold one call's outcome into the EWMA rate and decide `isOpen` in one atomic round trip — called on every closed-phase call, not just failures.
|
|
115
|
-
- `claimTrial` should be a conditional "create if absent" write (`SET key
|
|
127
|
+
- `claimTrial` should be a conditional "create if absent" write (`SET key token NX EX ttl` in Redis, with `token` a fresh unique value per call, e.g. a UUID) — it's what makes half-open recovery exclusive to one caller instead of a free-for-all. Return the token you wrote if this call won the claim, or `null` if the key was already taken.
|
|
128
|
+
- `releaseTrial` should be a compare-and-delete (`if GET key == token then DEL key` in Redis, a conditional delete elsewhere), not an unconditional delete. This is what stops a trial that outran its TTL (see [item 11](#whats-still-a-fundamental-tradeoff-not-a-bug)) from deleting a *different* instance's newer claim on the same key when it finally gets around to releasing its own now-stale one. If omitted (or if a call has no confirmed ownership token to release at all — e.g. `claimTrial` itself errored), redeye logs a one-time warning and leaves the claim for its TTL to expire naturally, rather than risk an unconditional delete that could destroy a claim it never confirmed was its own.
|
|
116
129
|
|
|
117
130
|
Implement the two required methods against Memcached, DynamoDB, your own cache wrapper, etc., and you have a working (best-effort) distributed breaker. Add the optional methods relevant to the strategy you use when that store supports a real atomic increment and a real conditional write, and you get the full reliability guarantees.
|
|
118
131
|
|
|
119
132
|
## API
|
|
120
133
|
|
|
121
134
|
- `execute(operation, fn)` — runs `fn` if the breaker allows it (closed, or this call won the half-open trial); throws immediately without calling `fn` otherwise. Records the outcome automatically.
|
|
122
|
-
- `canExecute(operation)` — synchronous, read-only, best-effort check. **Always returns `true` in distributed mode** (it can't await the store) — use `canExecuteAsync` there. Never claims a trial slot.
|
|
135
|
+
- `canExecute(operation)` — synchronous, read-only, best-effort check. **Always returns `true` in distributed mode** (it can't await the store) — use `canExecuteAsync` there. Never claims a trial slot. Logs a one-time warning the first time it's called in distributed mode, since a `true` there doesn't reflect real breaker state.
|
|
123
136
|
- `canExecuteAsync(operation)` — async, store-aware, read-only check. Honors `failOpenOnStoreError`. Never claims a trial slot — see the TOCTOU note below.
|
|
124
137
|
- `recordFailure(operation)` / `recordSuccess(operation)` — manually record an outcome without routing the call through `execute`. Note: these bypass the half-open trial-claim mechanism entirely (see [limitations](#reliability-model--limitations)) — prefer `execute`.
|
|
125
138
|
- `getState(operation)` — returns `{ failures, lastFailure, isOpen, openCount, errorRate, sampleCount }`. `openCount` is how many consecutive half-open trials have failed since the breaker last fully closed (drives backoff). `errorRate`/`sampleCount` are only meaningful under `strategy: 'errorRate'`.
|
|
@@ -127,6 +140,10 @@ Implement the two required methods against Memcached, DynamoDB, your own cache w
|
|
|
127
140
|
- `reset(operation)` — manually closes the breaker for an operation.
|
|
128
141
|
- `destroy()` — stops the internal monitor interval. Call this when a breaker instance is no longer needed (e.g. in tests, or on service shutdown) to avoid leaking a timer.
|
|
129
142
|
|
|
143
|
+
`operation` should be a small, fixed set of names (`'payment-gateway'`, `'fraud-api'`, one per dependency) — not something you interpolate per-request values into (a tenant ID, a URL, a user ID). Every distinct `operation` string gets its own entry in several per-instance maps (metrics, local-mode failure/backoff state, an internal jitter cache) that are never evicted, so a dynamic operation name is an unbounded memory leak, the same footgun as labeling a Prometheus metric with a high-cardinality value.
|
|
144
|
+
|
|
145
|
+
redeye can't stop you from doing this, but it can flag it: `execute`/`recordFailure`/`recordSuccess` log a one-time warning the first time they see an `operation` name over 100 characters or containing `/` (both common signs of an interpolated URL or ID), and — if you set `maxOperations` — a second one-time warning once the breaker has seen more distinct operation names than that. Neither check ever rejects a call; they're a smoke alarm, not enforcement.
|
|
146
|
+
|
|
130
147
|
## Options
|
|
131
148
|
|
|
132
149
|
| Option | Default | Description |
|
|
@@ -145,9 +162,10 @@ Implement the two required methods against Memcached, DynamoDB, your own cache w
|
|
|
145
162
|
| `timeout` | none | optional per-call timeout in ms |
|
|
146
163
|
| `store` | none | enables distributed mode when provided |
|
|
147
164
|
| `failOpenOnStoreError` | `true` | see [Store unavailability](#store-unavailability-fail-open-vs-fail-closed) |
|
|
148
|
-
| `onStateChange` | none | `(state: 'open' \| 'closed', operation: string) => void` |
|
|
165
|
+
| `onStateChange` | none | `(state: 'open' \| 'half-open' \| 'closed', operation: string) => void` — `'half-open'` fires exactly when a caller claims the single half-open trial slot. In distributed mode this is a per-process callback, not a fleet-wide broadcast — see [Observability](#what-redeye-actually-solves-with-redisstore-or-any-store-implementing-the-matching-optional-methods) below for which instance actually sees it. |
|
|
149
166
|
| `onStoreError` | none | `(error: unknown, operation: string) => void` — fired whenever a store read/write fails, in addition to being logged |
|
|
150
167
|
| `logger` | no-op | `{ warn(msg), log(msg) }` — plug in your own logger |
|
|
168
|
+
| `maxOperations` | none | Logs a one-time warning once the breaker has seen more than this many distinct `operation` names — see the cardinality note above. Unset: no limit, no warning. |
|
|
151
169
|
|
|
152
170
|
### Store unavailability: fail-open vs fail-closed
|
|
153
171
|
|
|
@@ -158,31 +176,62 @@ If the store itself throws (Redis is down, times out, network partition, etc.),
|
|
|
158
176
|
|
|
159
177
|
Writes back to the store are **always** best-effort — a write failure is logged and reported via `onStoreError`, but never thrown, and never overrides the real result of a call that already happened.
|
|
160
178
|
|
|
179
|
+
### Total coordination-layer outage (the store itself is down)
|
|
180
|
+
|
|
181
|
+
Same `failOpenOnStoreError` branch as above, just hit by every instance at once instead of one partitioned instance — redeye doesn't promote a backup coordinator or fall back to per-instance local tracking as a substitute:
|
|
182
|
+
|
|
183
|
+
- **`true` (default):** every instance lets every call through — no breaking happens anywhere, fleet-wide, for as long as the outage lasts.
|
|
184
|
+
- **`false`:** every instance blocks every call with `StoreUnavailableError`, fleet-wide, including requests that would have succeeded.
|
|
185
|
+
|
|
186
|
+
Nothing is buffered or replayed: outcomes during the outage are never recorded, and the breaker has no memory of the blackout once the store recovers. There's also no back-off from hitting a store known to be down — every guarded call keeps retrying it, so pair `failOpenOnStoreError: false` with fail-fast client options (`ioredis`'s `maxRetriesPerRequest`, `enableOfflineQueue: false`) if you don't want calls queuing on the client's own reconnect logic. Recovery is instant and automatic on the next successful read — no warm-up, no manual reset.
|
|
187
|
+
|
|
188
|
+
High availability of the store itself (Sentinel, Cluster) is your responsibility, configured on the client you hand to `RedisStore` — whatever failover consistency that setup provides is inherited as-is (see [Split-brain](#split-brain-whats-prevented-and-what-isnt)).
|
|
189
|
+
|
|
161
190
|
## Reliability model & limitations
|
|
162
191
|
|
|
163
192
|
### What redeye actually solves (with `RedisStore`, or any store implementing the matching optional methods)
|
|
164
193
|
|
|
165
194
|
- **Exact counting under concurrent failure, for both strategies.** `recordFailureAtomic` (consecutive) and `recordOutcomeAtomic` (errorRate) each run as a single Lua script inside Redis's single-threaded execution — two instances updating at the same instant cannot race and lose an update the way a plain get-then-set would.
|
|
166
195
|
- **Catches flapping, not just hard drops.** `strategy: 'errorRate'` trips on a smoothed failure *rate* once enough samples are seen, so a dependency that succeeds 1 in 5 requests (an 80% failure rate) still trips the breaker even though it never fails N times consecutively — a case `'consecutive'` structurally cannot catch, by design (see [Two tripping strategies](#two-tripping-strategies)).
|
|
167
|
-
- **Real half-open, single-trial recovery.** When the reset window elapses, callers don't all rush in — one caller atomically claims the trial slot (`claimTrial`, a conditional write) and the rest stay blocked (`Circuit breaker is open`) until that trial resolves. This is the classic Hystrix-style half-open state, not "everyone tries at once." Applies to both strategies.
|
|
196
|
+
- **Real half-open, single-trial recovery.** When the reset window elapses, callers don't all rush in — one caller atomically claims the trial slot (`claimTrial`, a conditional write) and the rest stay blocked (`Circuit breaker is open`) until that trial resolves. This is the classic Hystrix-style half-open state, not "everyone tries at once." Applies to both strategies. A single successful trial fully closes the breaker — redeye does not support requiring N consecutive successful trials before closing; that's intentionally out of scope for now, not an oversight.
|
|
168
197
|
- **Exponential backoff with jitter.** A dependency that keeps failing its trial is retried less often each time (`resetTimeout * backoffMultiplier ^ openCount`, capped at `maxResetTimeout`), and the exact retry moment is jittered per-instance so a cluster doesn't hammer a recovering dependency in lockstep.
|
|
169
198
|
- **No hard dependency on precise TTL timing for correctness.** The gating decision is based on elapsed time since the last recorded failure, not "did the key vanish yet" — the store's TTL is a generous safety-net for cleanup, not the primary mechanism. (Early eviction is still possible — see below — but it degrades gracefully instead of being load-bearing.)
|
|
170
199
|
- **Store outages are a distinct, handled condition**, not silently misattributed as the protected operation failing (see fail-open/fail-closed above).
|
|
171
|
-
- **Observability**: per-instance call/success/failure/rejection/store-error counters via `getMetrics`, plus `onStateChange` and `onStoreError` hooks.
|
|
200
|
+
- **Observability**: per-instance call/success/failure/rejection/store-error counters via `getMetrics`, plus `onStateChange` and `onStoreError` hooks. In distributed mode, `onStateChange` is invoked locally by whichever instance's own call happens to trigger a given transition — not broadcast to the rest of the fleet. Concretely: `'open'` fires only on the instance whose write is the one that crosses the threshold (or whose failed trial reopens it); `'half-open'` fires only on the instance that wins the trial claim; `'closed'` fires only on the instance that closes it (via a successful trial, or a manual `recordSuccess()`/`reset()` call). Every other instance sharing that operation still sees the new state reflected in their own gating decisions immediately — they just never get their own `onStateChange` call for a transition they didn't personally cause. If you need a fleet-wide notification (e.g. to page on-call once, not once per instance that happens to notice), de-duplicate downstream of the hook, or drive alerting off the store directly instead.
|
|
172
201
|
|
|
173
202
|
If your store *doesn't* implement the atomic method your chosen strategy needs (`recordFailureAtomic` or `recordOutcomeAtomic`) or `claimTrial`, redeye logs a one-time warning per missing capability and falls back to a non-atomic get-then-set — it still works, just without the atomicity/exclusivity guarantee for that piece.
|
|
174
203
|
|
|
204
|
+
### Split-brain: what's prevented, and what isn't
|
|
205
|
+
|
|
206
|
+
There's no split-brain among your app instances in the classic sense, because instances never hold independent authoritative state to disagree over — every instance reads the store fresh before every single decision (`gateDistributed`) instead of trusting a locally cached opinion. The store is the only "brain"; instances are just readers/writers of it. Two mechanisms enforce agreement on the common path:
|
|
207
|
+
|
|
208
|
+
- **Atomic writes.** `recordFailureAtomic`/`recordOutcomeAtomic` run as one Lua script — GET, decode, increment, decide, SET — inside Redis's single-threaded execution, so two instances failing at the same instant can't both read the same count and both write the same increment.
|
|
209
|
+
- **Exclusive trial claim.** `claimTrial` is a `SET ... NX`, which Redis resolves atomically, so exactly one instance ever runs the half-open recovery probe — never two instances simultaneously deciding they're the one testing recovery.
|
|
210
|
+
|
|
211
|
+
So the design doesn't eliminate split-brain so much as route around it: it pushes the single-arbiter requirement onto the store and never lets an instance act on stale local state instead of asking the store. That said, there are real, narrow windows where instances *can* still disagree — each one is a deliberate availability-over-consistency choice, not a hidden gap:
|
|
212
|
+
|
|
213
|
+
- **An instance partitioned from the store fails open independently** (item 9 below) — during the partition, that one instance's view of the breaker can genuinely diverge from the rest of the fleet's.
|
|
214
|
+
- **A `claimTrial` error can rarely produce two "winners"** (item 10 below) — a narrow window traded for never permanently wedging the breaker open.
|
|
215
|
+
- **A slow trial outliving its claim's TTL is the *more likely* way to get two concurrent trials** (item 11 below) — routine for a slowly-recovering dependency, not rare like item 10.
|
|
216
|
+
- **The store's own replication/failover consistency is inherited, not solved** (item 12 below) — this library adds no consensus layer on top of whatever your Redis deployment already guarantees.
|
|
217
|
+
- **Clock skew causes timing disagreement, not state disagreement** (item 3 below) — it can shift exactly when a trial becomes eligible, but it cannot cause a double-trial, since that's arbitrated by the store, not by comparing clocks.
|
|
218
|
+
|
|
175
219
|
### What's still a fundamental tradeoff, not a bug
|
|
176
220
|
|
|
177
221
|
These are true of any distributed circuit breaker, rate limiter, or lock built on a shared store — not gaps specific to redeye:
|
|
178
222
|
|
|
179
|
-
1. **
|
|
180
|
-
2. **
|
|
181
|
-
3.
|
|
182
|
-
4.
|
|
183
|
-
5. **
|
|
184
|
-
6. **
|
|
185
|
-
7.
|
|
223
|
+
1. **Distributed mode costs two Redis round trips per guarded call, not zero.** Every `execute()` call does a gate read (`store.get`) before deciding whether to proceed, then a state write afterward — `closeDistributed`/`recordFailureAtomic` for `consecutive` (yes, every success writes too, not just failures, since closing is unconditional), `recordOutcomeAtomic` for `errorRate` (writes on every closed-phase call, success or failure, since the rate needs both to be meaningful). A resolving half-open trial adds a third round trip to release its claim. On a latency-sensitive path this is added tail latency, and Redis load that scales linearly with request volume — the opposite tradeoff from something like Envoy's outlier detection, which caches state locally with a short TTL and accepts bounded staleness instead of paying a store round trip per call. redeye chose per-call freshness over that; it's a reasonable choice for many services, but measure it before putting this in front of your highest-QPS call. Local mode has none of this cost — see [Local mode vs. distributed mode](#local-mode-vs-distributed-mode-which-do-you-need) if you're not sure you need shared state at all.
|
|
224
|
+
2. **Correctness depends on trusting your store.** If Redis evicts a breaker key early under memory pressure (e.g. `maxmemory-policy allkeys-lru` with `circuit_breaker:*` competing for space with everything else), the breaker can reset earlier than intended. Mitigate by giving circuit-breaker keys their own keyspace/DB with a policy that doesn't evict them, or by monitoring `onStoreError` and Redis memory pressure directly. This is not fixable in-library — it's an operational configuration matter.
|
|
225
|
+
3. **Distributed timing is sensitive to clock skew.** Backoff and jitter windows are computed by comparing each instance's local `Date.now()` against a `lastFailure` timestamp written by whichever instance recorded it. With reasonably synchronized clocks (standard NTP) this is a non-issue; on a fleet with significant clock drift, instances can disagree by that drift amount about exactly when a trial becomes eligible. This affects *timing* only — the half-open claim mechanism (`claimTrial`) still guarantees exactly one trial runs regardless of skew, so skew cannot cause a thundering herd, only a slightly early or late trial attempt.
|
|
226
|
+
4. **`recordFailure`/`recordSuccess`/`canExecuteAsync` don't participate in trial claiming.** Only `execute()` claims and releases the half-open trial slot. If you build your own call flow around the manual API instead of `execute()`, you lose the single-trial guarantee and get the old "everyone retries once elapsed" behavior for that flow. Prefer `execute()`.
|
|
227
|
+
5. **One strategy/threshold/backoff policy per breaker instance**, applied uniformly to every `operation` string passed to it. Use separate `CircuitBreaker` instances for dependencies that need different policies — and separate `RedisStore` key prefixes if two breakers share an operation name with different strategies (their state shapes are incompatible and will corrupt each other under the same key).
|
|
228
|
+
6. **Local mode has no cross-restart persistence**, by design — it's explicitly the zero-dependency option. Use distributed mode if breaker state needs to survive a process restart.
|
|
229
|
+
7. **Metrics are per-instance**, not automatically aggregated across your fleet — the same as any Prometheus counter you'd scrape per-pod. Aggregate them in your own metrics backend if you need a fleet-wide view.
|
|
230
|
+
8. **`errorRate` is EWMA-smoothed, not a precise sliding window.** It approximates "failure rate over roughly the last ~`1/(1-decay)` calls," not an exact count over an exact window — good enough to catch flapping dependencies, but the exact trip point for a given call sequence is a function of the decay math, not literally "N of the last M calls."
|
|
231
|
+
9. **A partitioned instance fails open on its own, independently of the rest of the fleet.** If an instance's own call to the store errors (that instance can't reach Redis, but others can), it doesn't consult anyone else — it applies `failOpenOnStoreError` locally (default `true`). For the duration of that partition, the isolated instance treats the breaker as closed while the rest of the fleet, still able to reach the store, correctly sees it open. This is scoped to exactly the partitioned instance for exactly the duration of the partition, and it's a deliberate choice: favoring that one instance staying available over it blocking calls based on a store it can't even confirm the state of.
|
|
232
|
+
10. **A `claimTrial` error can rarely let two instances both believe they won the trial.** If the `claimTrial` call itself throws (not "no key", an actual error), the gate does not block the caller — it fails open on the trial too (`allowed: true, isTrial: true`), because refusing here would mean a single store blip at exactly the wrong moment could permanently wedge the breaker open (no one could ever claim the trial again). If two instances hit that specific error in the same narrow window, both can proceed with a trial call. This trades a rare double-trial for never risking permanent lockout.
|
|
233
|
+
11. **The trial-claim TTL expiring mid-flight is a more likely double-trial window than item 10, and it's by design.** `claimTrial`'s key has a TTL of `trialTimeout` (default `min(timeout ?? 10000, resetTimeout)`). If the trial call itself runs *longer* than that TTL, the claim expires while the call is still in flight, and another instance can then claim a second trial against the same recovering dependency — this is the intended anti-wedging mechanism (nothing should be able to hold the exclusive slot forever), not a bug. It's also the routine case, not the rare one: a slowly-recovering dependency whose first trial takes 12 seconds against a 10-second default `trialTimeout` will hit this on every recovery attempt, not occasionally. Set `trialTimeout` comfortably above your dependency's real p99 recovery-check latency if avoiding this matters to you. **What this does *not* do, strictly bounded by the release mechanism:** cascade into a third concurrent trial. `claimTrial` returns a per-call ownership token, and releasing a claim is always either a compare-and-delete against that exact token or nothing at all — never an unconditional delete — so the original caller's own expired claim, once it finally gets released, can never destroy whichever *other* instance's claim now legitimately occupies the key. That makes this limitation "double trial, strictly bounded to two" rather than "double trial, possibly cascading further."
|
|
234
|
+
12. **`RedisStore` inherits Redis's own replication/failover consistency — it doesn't add a consensus layer on top.** A single Redis instance has nothing to split-brain over. But if you run Sentinel or Cluster behind it, a failover with asynchronous replication can lose the last few writes, and reading from a lagging replica can return stale state. `RedisStore` doesn't issue `WAIT` or otherwise wait for replica acknowledgment — it trusts whatever consistency guarantees your Redis deployment itself provides.
|
|
186
235
|
|
|
187
236
|
### What redeye deliberately does not try to be
|
|
188
237
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store } from './store';
|
|
2
2
|
import { CircuitBreakerState, CircuitMetrics } from './types';
|
|
3
|
-
export type CircuitState = 'closed' | 'open';
|
|
3
|
+
export type CircuitState = 'closed' | 'open' | 'half-open';
|
|
4
4
|
export interface BreakerLogger {
|
|
5
5
|
warn(message: string): void;
|
|
6
6
|
log(message: string): void;
|
|
@@ -103,6 +103,15 @@ export interface CircuitBreakerOptions {
|
|
|
103
103
|
failOpenOnStoreError?: boolean;
|
|
104
104
|
onStoreError?: (error: unknown, operation: string) => void;
|
|
105
105
|
logger?: BreakerLogger;
|
|
106
|
+
/**
|
|
107
|
+
* Warns (once) once the number of distinct `operation` names this breaker
|
|
108
|
+
* has seen exceeds this count. `operation` is meant to be a small, fixed
|
|
109
|
+
* set of dependency names — every distinct value gets its own entry in
|
|
110
|
+
* several per-instance maps that are never evicted, so a dynamic name
|
|
111
|
+
* (a tenant ID, a URL, a user ID interpolated in) leaks memory
|
|
112
|
+
* indefinitely. Unset (default): no limit, no warning. See README.
|
|
113
|
+
*/
|
|
114
|
+
maxOperations?: number;
|
|
106
115
|
}
|
|
107
116
|
/**
|
|
108
117
|
* A circuit breaker with an optional distributed mode.
|
|
@@ -123,7 +132,12 @@ export declare class CircuitBreaker {
|
|
|
123
132
|
private readonly options;
|
|
124
133
|
private readonly distributed;
|
|
125
134
|
private readonly warnedCapabilities;
|
|
135
|
+
private warnedCanExecuteInDistributedMode;
|
|
136
|
+
private readonly knownOperations;
|
|
137
|
+
private warnedMaxOperations;
|
|
138
|
+
private warnedDynamicOperationName;
|
|
126
139
|
private readonly metrics;
|
|
140
|
+
private readonly cachedResetTimeouts;
|
|
127
141
|
private readonly failures;
|
|
128
142
|
private readonly lastFailureTime;
|
|
129
143
|
private readonly openOperations;
|
|
@@ -137,6 +151,14 @@ export declare class CircuitBreaker {
|
|
|
137
151
|
/** Stops the local-mode monitor interval. Call this when the breaker is no longer needed. */
|
|
138
152
|
destroy(): void;
|
|
139
153
|
execute<T>(operation: string, fn: () => Promise<T>): Promise<T>;
|
|
154
|
+
/**
|
|
155
|
+
* One-time, best-effort warnings for `operation` values that look like a
|
|
156
|
+
* per-request value (a URL, a tenant/user ID) rather than a small, fixed
|
|
157
|
+
* dependency name — see the README note on why that leaks memory. Cheap
|
|
158
|
+
* heuristics only (length, slashes); not a validator, and never rejects a
|
|
159
|
+
* call.
|
|
160
|
+
*/
|
|
161
|
+
private checkOperationName;
|
|
140
162
|
/**
|
|
141
163
|
* Synchronous, best-effort, read-only check (never claims a trial slot).
|
|
142
164
|
* In distributed mode this cannot await the store, so it always returns
|
|
@@ -152,12 +174,34 @@ export declare class CircuitBreaker {
|
|
|
152
174
|
canExecuteAsync(operation: string): Promise<boolean>;
|
|
153
175
|
recordFailure(operation: string): void;
|
|
154
176
|
recordSuccess(operation: string): void;
|
|
177
|
+
/**
|
|
178
|
+
* Used by the manual `recordSuccess()` API only — `execute()`'s own
|
|
179
|
+
* success paths already know locally whether they're closing from a real
|
|
180
|
+
* trial (and fire `onStateChange` directly) or from an already-closed
|
|
181
|
+
* state (where firing would be spurious), so they call `closeDistributed`
|
|
182
|
+
* without this extra read. `recordSuccess()` has no such context — the
|
|
183
|
+
* caller might invoke it on a breaker that's actually open — so it pays
|
|
184
|
+
* for one extra read to detect a real transition, matching what `reset()`
|
|
185
|
+
* already does.
|
|
186
|
+
*/
|
|
187
|
+
private closeDistributedAndNotify;
|
|
155
188
|
getState(operation: string): Promise<CircuitBreakerState>;
|
|
156
189
|
reset(operation: string): Promise<void>;
|
|
157
190
|
/** Per-instance call counters for `operation`. In distributed mode this reflects only calls this instance handled — export it via your own metrics system and aggregate across instances, the same way you would any per-process Prometheus counter. */
|
|
158
191
|
getMetrics(operation: string): CircuitMetrics;
|
|
159
192
|
getAllMetrics(): Record<string, CircuitMetrics>;
|
|
160
193
|
private metricsFor;
|
|
194
|
+
private backoffCapped;
|
|
195
|
+
/**
|
|
196
|
+
* Jitter is rolled once per open "episode" — identified by (openCount,
|
|
197
|
+
* lastFailure), which only change when the breaker opens or a trial fails
|
|
198
|
+
* — and cached, not re-rolled on every gate check. Re-rolling per call
|
|
199
|
+
* would let callers keep sampling until a roll happens to pass, which
|
|
200
|
+
* systematically biases the effective earliest trial time toward
|
|
201
|
+
* `capped * (1 - jitter)` instead of spreading it around the nominal
|
|
202
|
+
* timeout, and could flip a call between "blocked" and "eligible" and
|
|
203
|
+
* back on consecutive checks milliseconds apart.
|
|
204
|
+
*/
|
|
161
205
|
private effectiveResetTimeout;
|
|
162
206
|
private key;
|
|
163
207
|
private trialKey;
|
|
@@ -169,8 +213,26 @@ export declare class CircuitBreaker {
|
|
|
169
213
|
private safeSet;
|
|
170
214
|
/** Deletes the main state key for `operation`. Best-effort: logged, never thrown. */
|
|
171
215
|
private safeDelMain;
|
|
172
|
-
/** Deletes the trial-claim key for `operation
|
|
216
|
+
/** Deletes the trial-claim key for `operation` unconditionally, releasing it early instead of waiting for its TTL. Only for a full reset/wipe — see `safeReleaseTrial` for releasing a specific held claim. Best-effort. */
|
|
173
217
|
private safeDelTrial;
|
|
218
|
+
/**
|
|
219
|
+
* Releases a trial claim this call actually won, early instead of
|
|
220
|
+
* waiting for its TTL. Uses a compare-and-delete (`Store.releaseTrial`)
|
|
221
|
+
* so a trial that outran its TTL can't delete a *different* instance's
|
|
222
|
+
* newer claim on the same key (see README limitation on trial-TTL
|
|
223
|
+
* expiry).
|
|
224
|
+
*
|
|
225
|
+
* Deliberately does *not* fall back to an unconditional delete when
|
|
226
|
+
* there's no token (the gate failed open on the trial without a
|
|
227
|
+
* confirmed claim — e.g. `claimTrial` itself errored) or the store lacks
|
|
228
|
+
* `releaseTrial` (an incomplete custom `Store`) — an unconditional delete
|
|
229
|
+
* in either case would recreate the exact bug this token scheme exists to
|
|
230
|
+
* prevent: deleting a claim we never confirmed is ours, which may by now
|
|
231
|
+
* belong to a different instance. The worst case for doing nothing is the
|
|
232
|
+
* slot staying occupied up to `trialTimeout` longer than it needs to —
|
|
233
|
+
* bounded and safe. Best-effort: logged, never thrown.
|
|
234
|
+
*/
|
|
235
|
+
private safeReleaseTrial;
|
|
174
236
|
private closeDistributed;
|
|
175
237
|
/**
|
|
176
238
|
* Determines whether a call is allowed through in distributed mode.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAA8B,MAAM,SAAS,CAAC;AAE1F,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
package/dist/circuit-breaker.js
CHANGED
|
@@ -35,7 +35,12 @@ const noopLogger = { warn: () => { }, log: () => { } };
|
|
|
35
35
|
class CircuitBreaker {
|
|
36
36
|
constructor(options = {}) {
|
|
37
37
|
this.warnedCapabilities = new Set();
|
|
38
|
+
this.warnedCanExecuteInDistributedMode = false;
|
|
39
|
+
this.knownOperations = new Set();
|
|
40
|
+
this.warnedMaxOperations = false;
|
|
41
|
+
this.warnedDynamicOperationName = false;
|
|
38
42
|
this.metrics = new Map();
|
|
43
|
+
this.cachedResetTimeouts = new Map();
|
|
39
44
|
// local mode state
|
|
40
45
|
this.failures = new Map();
|
|
41
46
|
this.lastFailureTime = new Map();
|
|
@@ -64,6 +69,7 @@ class CircuitBreaker {
|
|
|
64
69
|
failOpenOnStoreError: options.failOpenOnStoreError ?? true,
|
|
65
70
|
onStoreError: options.onStoreError,
|
|
66
71
|
logger: options.logger ?? noopLogger,
|
|
72
|
+
maxOperations: options.maxOperations,
|
|
67
73
|
};
|
|
68
74
|
this.distributed = !!options.store;
|
|
69
75
|
this.monitorHandle = setInterval(() => this.monitor(), this.options.monitorInterval);
|
|
@@ -74,15 +80,44 @@ class CircuitBreaker {
|
|
|
74
80
|
clearInterval(this.monitorHandle);
|
|
75
81
|
}
|
|
76
82
|
async execute(operation, fn) {
|
|
83
|
+
this.checkOperationName(operation);
|
|
77
84
|
return this.distributed ? this.executeDistributed(operation, fn) : this.executeLocal(operation, fn);
|
|
78
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* One-time, best-effort warnings for `operation` values that look like a
|
|
88
|
+
* per-request value (a URL, a tenant/user ID) rather than a small, fixed
|
|
89
|
+
* dependency name — see the README note on why that leaks memory. Cheap
|
|
90
|
+
* heuristics only (length, slashes); not a validator, and never rejects a
|
|
91
|
+
* call.
|
|
92
|
+
*/
|
|
93
|
+
checkOperationName(operation) {
|
|
94
|
+
if (!this.warnedDynamicOperationName && (operation.length > 100 || operation.includes('/'))) {
|
|
95
|
+
this.warnedDynamicOperationName = true;
|
|
96
|
+
const shown = operation.length > 100 ? `${operation.slice(0, 100)}…` : operation;
|
|
97
|
+
this.options.logger.warn(`Circuit breaker operation name "${shown}" looks dynamic (${operation.length > 100 ? `${operation.length} chars` : 'contains "/"'}). operation should be a small, fixed set of names (e.g. "payment-gateway"), not a value interpolated per request (a URL, tenant ID, user ID) — every distinct name is tracked forever and never evicted. See README.`);
|
|
98
|
+
}
|
|
99
|
+
if (this.options.maxOperations !== undefined && !this.warnedMaxOperations && !this.knownOperations.has(operation)) {
|
|
100
|
+
this.knownOperations.add(operation);
|
|
101
|
+
if (this.knownOperations.size > this.options.maxOperations) {
|
|
102
|
+
this.warnedMaxOperations = true;
|
|
103
|
+
this.options.logger.warn(`Circuit breaker has seen ${this.knownOperations.size} distinct operation names, exceeding maxOperations (${this.options.maxOperations}). This usually means operation names are dynamic instead of a small fixed set, which leaks memory indefinitely. See README.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
79
107
|
/**
|
|
80
108
|
* Synchronous, best-effort, read-only check (never claims a trial slot).
|
|
81
109
|
* In distributed mode this cannot await the store, so it always returns
|
|
82
110
|
* `true` — use `canExecuteAsync` there.
|
|
83
111
|
*/
|
|
84
112
|
canExecute(operation) {
|
|
85
|
-
|
|
113
|
+
if (this.distributed) {
|
|
114
|
+
if (!this.warnedCanExecuteInDistributedMode) {
|
|
115
|
+
this.warnedCanExecuteInDistributedMode = true;
|
|
116
|
+
this.options.logger.warn('canExecute() always returns true in distributed mode (it cannot await the store) and does not reflect real breaker state; use canExecuteAsync() instead.');
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return this.peekLocalGate(operation);
|
|
86
121
|
}
|
|
87
122
|
/**
|
|
88
123
|
* Async, store-aware, read-only check (never claims a trial slot — use
|
|
@@ -97,6 +132,7 @@ class CircuitBreaker {
|
|
|
97
132
|
return gate.allowed;
|
|
98
133
|
}
|
|
99
134
|
recordFailure(operation) {
|
|
135
|
+
this.checkOperationName(operation);
|
|
100
136
|
if (this.distributed) {
|
|
101
137
|
if (this.options.strategy === 'errorRate') {
|
|
102
138
|
void this.recordOutcomeDistributed(operation, false);
|
|
@@ -113,13 +149,31 @@ class CircuitBreaker {
|
|
|
113
149
|
}
|
|
114
150
|
}
|
|
115
151
|
recordSuccess(operation) {
|
|
152
|
+
this.checkOperationName(operation);
|
|
116
153
|
if (this.distributed) {
|
|
117
|
-
void this.
|
|
154
|
+
void this.closeDistributedAndNotify(operation);
|
|
118
155
|
}
|
|
119
156
|
else {
|
|
120
157
|
this.resetLocal(operation);
|
|
121
158
|
}
|
|
122
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Used by the manual `recordSuccess()` API only — `execute()`'s own
|
|
162
|
+
* success paths already know locally whether they're closing from a real
|
|
163
|
+
* trial (and fire `onStateChange` directly) or from an already-closed
|
|
164
|
+
* state (where firing would be spurious), so they call `closeDistributed`
|
|
165
|
+
* without this extra read. `recordSuccess()` has no such context — the
|
|
166
|
+
* caller might invoke it on a breaker that's actually open — so it pays
|
|
167
|
+
* for one extra read to detect a real transition, matching what `reset()`
|
|
168
|
+
* already does.
|
|
169
|
+
*/
|
|
170
|
+
async closeDistributedAndNotify(operation) {
|
|
171
|
+
const prior = await this.safeGet(operation);
|
|
172
|
+
await this.closeDistributed(operation);
|
|
173
|
+
if (prior?.isOpen) {
|
|
174
|
+
this.options.onStateChange?.('closed', operation);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
123
177
|
async getState(operation) {
|
|
124
178
|
if (this.distributed) {
|
|
125
179
|
return (await this.safeGet(operation)) ?? { ...types_1.CLOSED_STATE };
|
|
@@ -136,6 +190,7 @@ class CircuitBreaker {
|
|
|
136
190
|
const prior = await this.safeGet(operation);
|
|
137
191
|
await this.safeDelMain(operation);
|
|
138
192
|
await this.safeDelTrial(operation);
|
|
193
|
+
this.cachedResetTimeouts.delete(operation);
|
|
139
194
|
if (prior?.isOpen) {
|
|
140
195
|
this.options.onStateChange?.('closed', operation);
|
|
141
196
|
}
|
|
@@ -165,13 +220,33 @@ class CircuitBreaker {
|
|
|
165
220
|
return m;
|
|
166
221
|
}
|
|
167
222
|
// ---- backoff / jitter -------------------------------------------------
|
|
168
|
-
|
|
223
|
+
backoffCapped(openCount) {
|
|
169
224
|
const backed = this.options.resetTimeout * Math.pow(this.options.backoffMultiplier, openCount);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
225
|
+
return Math.min(backed, this.options.maxResetTimeout);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Jitter is rolled once per open "episode" — identified by (openCount,
|
|
229
|
+
* lastFailure), which only change when the breaker opens or a trial fails
|
|
230
|
+
* — and cached, not re-rolled on every gate check. Re-rolling per call
|
|
231
|
+
* would let callers keep sampling until a roll happens to pass, which
|
|
232
|
+
* systematically biases the effective earliest trial time toward
|
|
233
|
+
* `capped * (1 - jitter)` instead of spreading it around the nominal
|
|
234
|
+
* timeout, and could flip a call between "blocked" and "eligible" and
|
|
235
|
+
* back on consecutive checks milliseconds apart.
|
|
236
|
+
*/
|
|
237
|
+
effectiveResetTimeout(operation, openCount, lastFailure) {
|
|
238
|
+
const cached = this.cachedResetTimeouts.get(operation);
|
|
239
|
+
if (cached && cached.openCount === openCount && cached.lastFailure === lastFailure) {
|
|
240
|
+
return cached.value;
|
|
241
|
+
}
|
|
242
|
+
const capped = this.backoffCapped(openCount);
|
|
243
|
+
let value = capped;
|
|
244
|
+
if (this.options.jitter) {
|
|
245
|
+
const delta = capped * this.options.jitter;
|
|
246
|
+
value = capped + (Math.random() * 2 - 1) * delta;
|
|
247
|
+
}
|
|
248
|
+
this.cachedResetTimeouts.set(operation, { openCount, lastFailure, value });
|
|
249
|
+
return value;
|
|
175
250
|
}
|
|
176
251
|
// ---- distributed mode -----------------------------------------------
|
|
177
252
|
key(operation) {
|
|
@@ -184,8 +259,10 @@ class CircuitBreaker {
|
|
|
184
259
|
// A generous safety-net TTL, decoupled from the actual gating decision
|
|
185
260
|
// (which uses lastFailure + effectiveResetTimeout below) so early
|
|
186
261
|
// eviction degrades gracefully rather than being the sole correctness
|
|
187
|
-
// mechanism. See README limitation on store TTL trust.
|
|
188
|
-
|
|
262
|
+
// mechanism. See README limitation on store TTL trust. Uses the
|
|
263
|
+
// unjittered bound — jitter exists to spread out gating decisions, not
|
|
264
|
+
// to vary a generous cleanup TTL.
|
|
265
|
+
return Math.max(1, Math.ceil((this.backoffCapped(openCount) * 3) / 1000));
|
|
189
266
|
}
|
|
190
267
|
trialTtlSeconds() {
|
|
191
268
|
return Math.max(1, Math.ceil(this.options.trialTimeout / 1000));
|
|
@@ -227,7 +304,7 @@ class CircuitBreaker {
|
|
|
227
304
|
this.reportStoreError(error, operation);
|
|
228
305
|
}
|
|
229
306
|
}
|
|
230
|
-
/** Deletes the trial-claim key for `operation
|
|
307
|
+
/** Deletes the trial-claim key for `operation` unconditionally, releasing it early instead of waiting for its TTL. Only for a full reset/wipe — see `safeReleaseTrial` for releasing a specific held claim. Best-effort. */
|
|
231
308
|
async safeDelTrial(operation) {
|
|
232
309
|
try {
|
|
233
310
|
await this.options.store.del(this.trialKey(operation));
|
|
@@ -236,8 +313,40 @@ class CircuitBreaker {
|
|
|
236
313
|
this.reportStoreError(error, operation);
|
|
237
314
|
}
|
|
238
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Releases a trial claim this call actually won, early instead of
|
|
318
|
+
* waiting for its TTL. Uses a compare-and-delete (`Store.releaseTrial`)
|
|
319
|
+
* so a trial that outran its TTL can't delete a *different* instance's
|
|
320
|
+
* newer claim on the same key (see README limitation on trial-TTL
|
|
321
|
+
* expiry).
|
|
322
|
+
*
|
|
323
|
+
* Deliberately does *not* fall back to an unconditional delete when
|
|
324
|
+
* there's no token (the gate failed open on the trial without a
|
|
325
|
+
* confirmed claim — e.g. `claimTrial` itself errored) or the store lacks
|
|
326
|
+
* `releaseTrial` (an incomplete custom `Store`) — an unconditional delete
|
|
327
|
+
* in either case would recreate the exact bug this token scheme exists to
|
|
328
|
+
* prevent: deleting a claim we never confirmed is ours, which may by now
|
|
329
|
+
* belong to a different instance. The worst case for doing nothing is the
|
|
330
|
+
* slot staying occupied up to `trialTimeout` longer than it needs to —
|
|
331
|
+
* bounded and safe. Best-effort: logged, never thrown.
|
|
332
|
+
*/
|
|
333
|
+
async safeReleaseTrial(operation, token) {
|
|
334
|
+
if (!token)
|
|
335
|
+
return;
|
|
336
|
+
if (!this.options.store.releaseTrial) {
|
|
337
|
+
this.warnMissingCapability('releaseTrial');
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
await this.options.store.releaseTrial(this.trialKey(operation), token);
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
this.reportStoreError(error, operation);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
239
347
|
async closeDistributed(operation) {
|
|
240
348
|
await this.safeSet(operation, { ...types_1.CLOSED_STATE }, this.stateTtlSeconds(0));
|
|
349
|
+
this.cachedResetTimeouts.delete(operation);
|
|
241
350
|
}
|
|
242
351
|
/**
|
|
243
352
|
* Determines whether a call is allowed through in distributed mode.
|
|
@@ -258,7 +367,7 @@ class CircuitBreaker {
|
|
|
258
367
|
}
|
|
259
368
|
if (!state?.isOpen)
|
|
260
369
|
return { allowed: true, isTrial: false };
|
|
261
|
-
const effective = this.effectiveResetTimeout(state.openCount ?? 0);
|
|
370
|
+
const effective = this.effectiveResetTimeout(operation, state.openCount ?? 0, state.lastFailure);
|
|
262
371
|
if (Date.now() - state.lastFailure < effective) {
|
|
263
372
|
return { allowed: false, isTrial: false };
|
|
264
373
|
}
|
|
@@ -266,18 +375,22 @@ class CircuitBreaker {
|
|
|
266
375
|
return { allowed: true, isTrial: false };
|
|
267
376
|
if (this.options.store.claimTrial) {
|
|
268
377
|
try {
|
|
269
|
-
const
|
|
270
|
-
|
|
378
|
+
const token = await this.options.store.claimTrial(this.trialKey(operation), this.trialTtlSeconds());
|
|
379
|
+
if (token)
|
|
380
|
+
this.options.onStateChange?.('half-open', operation);
|
|
381
|
+
return { allowed: token !== null, isTrial: token !== null, trialToken: token ?? undefined };
|
|
271
382
|
}
|
|
272
383
|
catch (error) {
|
|
273
384
|
this.reportStoreError(error, operation);
|
|
274
385
|
if (!this.options.failOpenOnStoreError)
|
|
275
386
|
throw new StoreUnavailableError(operation, error);
|
|
276
387
|
// Can't confirm exclusivity — fail open on the trial itself rather than deadlocking forever.
|
|
388
|
+
this.options.onStateChange?.('half-open', operation);
|
|
277
389
|
return { allowed: true, isTrial: true };
|
|
278
390
|
}
|
|
279
391
|
}
|
|
280
392
|
this.warnMissingCapability('claimTrial');
|
|
393
|
+
this.options.onStateChange?.('half-open', operation);
|
|
281
394
|
return { allowed: true, isTrial: true };
|
|
282
395
|
}
|
|
283
396
|
async executeDistributed(operation, fn) {
|
|
@@ -293,7 +406,8 @@ class CircuitBreaker {
|
|
|
293
406
|
metrics.totalSuccesses++;
|
|
294
407
|
if (gate.isTrial) {
|
|
295
408
|
await this.closeDistributed(operation);
|
|
296
|
-
await this.
|
|
409
|
+
await this.safeReleaseTrial(operation, gate.trialToken);
|
|
410
|
+
this.options.onStateChange?.('closed', operation);
|
|
297
411
|
}
|
|
298
412
|
else if (this.options.strategy === 'errorRate') {
|
|
299
413
|
await this.recordOutcomeDistributed(operation, true);
|
|
@@ -307,7 +421,7 @@ class CircuitBreaker {
|
|
|
307
421
|
metrics.totalFailures++;
|
|
308
422
|
if (gate.isTrial) {
|
|
309
423
|
await this.reopenAfterFailedTrialDistributed(operation);
|
|
310
|
-
await this.
|
|
424
|
+
await this.safeReleaseTrial(operation, gate.trialToken);
|
|
311
425
|
}
|
|
312
426
|
else if (this.options.strategy === 'errorRate') {
|
|
313
427
|
await this.recordOutcomeDistributed(operation, false);
|
|
@@ -346,7 +460,12 @@ class CircuitBreaker {
|
|
|
346
460
|
failures: current.failures + 1,
|
|
347
461
|
lastFailure: Date.now(),
|
|
348
462
|
isOpen: current.failures + 1 >= this.options.failureThreshold,
|
|
349
|
-
|
|
463
|
+
// Preserve, don't reset: a closed-phase failure can't normally happen
|
|
464
|
+
// while the breaker is open, but under failOpenOnStoreError a store
|
|
465
|
+
// blip on the gate read can let a call proceed while state.isOpen is
|
|
466
|
+
// still true elsewhere, and this write must not wipe accumulated
|
|
467
|
+
// backoff if that call then fails and lands here.
|
|
468
|
+
openCount: current.openCount ?? 0,
|
|
350
469
|
errorRate: current.errorRate ?? 0,
|
|
351
470
|
sampleCount: current.sampleCount ?? 0,
|
|
352
471
|
};
|
|
@@ -419,6 +538,7 @@ class CircuitBreaker {
|
|
|
419
538
|
};
|
|
420
539
|
await this.safeSet(operation, next, this.stateTtlSeconds(openCount));
|
|
421
540
|
this.options.logger.warn(`Half-open trial failed for operation: ${operation}; backing off (attempt ${openCount + 1})`);
|
|
541
|
+
this.options.onStateChange?.('open', operation);
|
|
422
542
|
}
|
|
423
543
|
// ---- local mode -------------------------------------------------------
|
|
424
544
|
async executeLocal(operation, fn) {
|
|
@@ -463,7 +583,7 @@ class CircuitBreaker {
|
|
|
463
583
|
return true;
|
|
464
584
|
const openCount = this.openCounts.get(operation) ?? 0;
|
|
465
585
|
const lastFailure = this.lastFailureTime.get(operation) ?? 0;
|
|
466
|
-
const effective = this.effectiveResetTimeout(openCount);
|
|
586
|
+
const effective = this.effectiveResetTimeout(operation, openCount, lastFailure);
|
|
467
587
|
if (Date.now() - lastFailure < effective) {
|
|
468
588
|
this.options.logger.warn(`Circuit breaker open for operation: ${operation}`);
|
|
469
589
|
return false;
|
|
@@ -476,7 +596,7 @@ class CircuitBreaker {
|
|
|
476
596
|
return { allowed: true, isTrial: false };
|
|
477
597
|
const openCount = this.openCounts.get(operation) ?? 0;
|
|
478
598
|
const lastFailure = this.lastFailureTime.get(operation) ?? 0;
|
|
479
|
-
const effective = this.effectiveResetTimeout(openCount);
|
|
599
|
+
const effective = this.effectiveResetTimeout(operation, openCount, lastFailure);
|
|
480
600
|
if (Date.now() - lastFailure < effective) {
|
|
481
601
|
this.options.logger.warn(`Circuit breaker open for operation: ${operation}`);
|
|
482
602
|
return { allowed: false, isTrial: false };
|
|
@@ -487,6 +607,7 @@ class CircuitBreaker {
|
|
|
487
607
|
}
|
|
488
608
|
this.trialInProgress.add(operation);
|
|
489
609
|
this.trialClaimedAt.set(operation, Date.now());
|
|
610
|
+
this.options.onStateChange?.('half-open', operation);
|
|
490
611
|
return { allowed: true, isTrial: true };
|
|
491
612
|
}
|
|
492
613
|
recordFailureLocalCounting(operation) {
|
|
@@ -523,6 +644,7 @@ class CircuitBreaker {
|
|
|
523
644
|
this.openCounts.set(operation, openCount);
|
|
524
645
|
this.lastFailureTime.set(operation, Date.now());
|
|
525
646
|
this.options.logger.warn(`Half-open trial failed for operation: ${operation}; backing off (attempt ${openCount + 1})`);
|
|
647
|
+
this.options.onStateChange?.('open', operation);
|
|
526
648
|
}
|
|
527
649
|
resetLocal(operation) {
|
|
528
650
|
const wasOpen = this.openOperations.has(operation);
|
|
@@ -534,6 +656,7 @@ class CircuitBreaker {
|
|
|
534
656
|
this.trialClaimedAt.delete(operation);
|
|
535
657
|
this.errorRates.delete(operation);
|
|
536
658
|
this.sampleCounts.delete(operation);
|
|
659
|
+
this.cachedResetTimeouts.delete(operation);
|
|
537
660
|
if (wasOpen) {
|
|
538
661
|
this.options.onStateChange?.('closed', operation);
|
|
539
662
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -18,16 +18,36 @@ export interface Store {
|
|
|
18
18
|
}): Promise<CircuitBreakerState>;
|
|
19
19
|
/**
|
|
20
20
|
* Atomically claims a short-lived, exclusive "trial" slot for `key`
|
|
21
|
-
* (conceptually a SET-if-not-exists). Returns
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* (conceptually a SET-if-not-exists). Returns an ownership token (an
|
|
22
|
+
* opaque string) if this call won the claim, or `null` if someone else
|
|
23
|
+
* already holds it. Used to implement half-open: only the winner gets to
|
|
24
|
+
* make the trial call while a breaker is transitioning from open back to
|
|
25
|
+
* closed; everyone else stays blocked until the trial resolves.
|
|
26
|
+
*
|
|
27
|
+
* Release the claim via `releaseTrial` with this same token when the
|
|
28
|
+
* trial resolves — never delete the key unconditionally. If the trial
|
|
29
|
+
* outran its TTL, another instance may have since claimed a *new* trial
|
|
30
|
+
* on the same key (see README limitation on trial-TTL expiry, which is
|
|
31
|
+
* by design); an unconditional delete at that point would destroy that
|
|
32
|
+
* other instance's active claim instead of the caller's own expired one.
|
|
25
33
|
*
|
|
26
34
|
* If omitted, the breaker falls back to letting every caller through
|
|
27
35
|
* once the reset window elapses (a thundering herd on recovery — see
|
|
28
36
|
* README).
|
|
29
37
|
*/
|
|
30
|
-
claimTrial?(key: string, ttlSeconds: number): Promise<
|
|
38
|
+
claimTrial?(key: string, ttlSeconds: number): Promise<string | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Releases a trial slot claimed via `claimTrial`, but only if `token`
|
|
41
|
+
* still matches what's currently stored under `key` — a compare-and-
|
|
42
|
+
* delete, not an unconditional delete. This is what prevents a trial
|
|
43
|
+
* that outran its TTL from later deleting a *different* instance's newer
|
|
44
|
+
* claim on the same key.
|
|
45
|
+
*
|
|
46
|
+
* If omitted, the breaker logs a one-time warning and does not delete the
|
|
47
|
+
* key at all — claims are then released only by TTL expiry, so recovery
|
|
48
|
+
* after a resolved trial can lag by up to the trial TTL.
|
|
49
|
+
*/
|
|
50
|
+
releaseTrial?(key: string, token: string): Promise<void>;
|
|
31
51
|
/**
|
|
32
52
|
* `strategy: 'errorRate'` only. Atomically folds one call's outcome into
|
|
33
53
|
* an EWMA failure-rate estimate and decides `isOpen` in a single round
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC;;;;;;;OAOG;IACH,mBAAmB,CAAC,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEhC
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC;;;;;;;OAOG;IACH,mBAAmB,CAAC,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEhC;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAErE;;;;;;;;;;OAUG;IACH,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;;;;;;;;;;;OAYG;IACH,mBAAmB,CAAC,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAC3H,OAAO,CAAC,mBAAmB,GAAG;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1D"}
|
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
import type { Redis } from 'ioredis';
|
|
1
|
+
import type { Redis, Result } from 'ioredis';
|
|
2
2
|
import { Store } from '../store';
|
|
3
3
|
import { CircuitBreakerState } from '../types';
|
|
4
|
+
declare module 'ioredis' {
|
|
5
|
+
interface RedisCommander<Context> {
|
|
6
|
+
redeyeRecordFailure(key: string, ttlSeconds: number, failureThreshold: number, now: number): Result<string, Context>;
|
|
7
|
+
redeyeRecordOutcome(key: string, decay: number, isFailure: number, minimumCalls: number, errorRateThreshold: number, ttlSeconds: number, now: number): Result<string, Context>;
|
|
8
|
+
redeyeReleaseTrial(key: string, token: string): Result<number, Context>;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* Redis-backed Store implementation. Import this from
|
|
6
13
|
* `redeye/redis-store` so the core package has no hard dependency on
|
|
7
14
|
* `ioredis` — only consumers who use RedisStore need it installed.
|
|
8
15
|
*
|
|
9
16
|
* Implements all three optional atomic capabilities (`recordFailureAtomic`
|
|
10
|
-
* and `recordOutcomeAtomic` via Lua scripts, `claimTrial` via
|
|
11
|
-
*
|
|
12
|
-
*
|
|
17
|
+
* and `recordOutcomeAtomic` via Lua scripts, `claimTrial`/`releaseTrial` via
|
|
18
|
+
* a tokened `SET ... NX` and compare-and-delete), so breakers backed by
|
|
19
|
+
* RedisStore get exact counting and real single-trial half-open behavior
|
|
20
|
+
* under both strategies instead of best-effort fallbacks.
|
|
21
|
+
*
|
|
22
|
+
* Scripts are registered once per Redis client via `defineCommand`, so
|
|
23
|
+
* ioredis sends a cached script hash (`EVALSHA`) on every call instead of
|
|
24
|
+
* the full script body, with automatic fallback to `EVAL` if the script
|
|
25
|
+
* cache is ever flushed.
|
|
13
26
|
*/
|
|
14
27
|
export declare class RedisStore implements Store {
|
|
15
28
|
private readonly redis;
|
|
@@ -35,6 +48,7 @@ export declare class RedisStore implements Store {
|
|
|
35
48
|
}): Promise<CircuitBreakerState & {
|
|
36
49
|
openedNow: boolean;
|
|
37
50
|
}>;
|
|
38
|
-
claimTrial(key: string, ttlSeconds: number): Promise<
|
|
51
|
+
claimTrial(key: string, ttlSeconds: number): Promise<string | null>;
|
|
52
|
+
releaseTrial(key: string, token: string): Promise<void>;
|
|
39
53
|
}
|
|
40
54
|
//# sourceMappingURL=redis-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis-store.d.ts","sourceRoot":"","sources":["../../src/stores/redis-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"redis-store.d.ts","sourceRoot":"","sources":["../../src/stores/redis-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc,CAAC,OAAO;QAC9B,mBAAmB,CACjB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3B,mBAAmB,CACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3B,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACzE;CACF;AA0GD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAW,YAAW,KAAK;IAG1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEH,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;IAOzE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAMtC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/B,mBAAmB,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,mBAAmB,CAAC;IAUzB,mBAAmB,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAC3H,OAAO,CAAC,mBAAmB,GAAG;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAalD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAMnE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RedisStore = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
4
5
|
/**
|
|
5
6
|
* Atomically increments the stored failure count and decides `isOpen` in one
|
|
6
7
|
* round trip: GET -> decode -> increment -> compute isOpen -> SET, all inside
|
|
@@ -87,20 +88,44 @@ for k, v in pairs(state) do result[k] = v end
|
|
|
87
88
|
result.openedNow = isOpen and not wasOpen
|
|
88
89
|
return cjson.encode(result)
|
|
89
90
|
`;
|
|
91
|
+
/**
|
|
92
|
+
* Compare-and-delete: releases a trial claim only if `token` still matches
|
|
93
|
+
* what's stored. Without this, releasing with a plain DEL can destroy a
|
|
94
|
+
* *different* instance's newer claim if the original trial outran its TTL
|
|
95
|
+
* and someone else has since claimed the key (see README limitation on
|
|
96
|
+
* trial-TTL expiry) — a stale release would otherwise cascade into an extra
|
|
97
|
+
* concurrent trial beyond the one that scenario already accepts by design.
|
|
98
|
+
*/
|
|
99
|
+
const RELEASE_TRIAL_SCRIPT = `
|
|
100
|
+
if redis.call('GET', KEYS[1]) == ARGV[1] then
|
|
101
|
+
return redis.call('DEL', KEYS[1])
|
|
102
|
+
else
|
|
103
|
+
return 0
|
|
104
|
+
end
|
|
105
|
+
`;
|
|
90
106
|
/**
|
|
91
107
|
* Redis-backed Store implementation. Import this from
|
|
92
108
|
* `redeye/redis-store` so the core package has no hard dependency on
|
|
93
109
|
* `ioredis` — only consumers who use RedisStore need it installed.
|
|
94
110
|
*
|
|
95
111
|
* Implements all three optional atomic capabilities (`recordFailureAtomic`
|
|
96
|
-
* and `recordOutcomeAtomic` via Lua scripts, `claimTrial` via
|
|
97
|
-
*
|
|
98
|
-
*
|
|
112
|
+
* and `recordOutcomeAtomic` via Lua scripts, `claimTrial`/`releaseTrial` via
|
|
113
|
+
* a tokened `SET ... NX` and compare-and-delete), so breakers backed by
|
|
114
|
+
* RedisStore get exact counting and real single-trial half-open behavior
|
|
115
|
+
* under both strategies instead of best-effort fallbacks.
|
|
116
|
+
*
|
|
117
|
+
* Scripts are registered once per Redis client via `defineCommand`, so
|
|
118
|
+
* ioredis sends a cached script hash (`EVALSHA`) on every call instead of
|
|
119
|
+
* the full script body, with automatic fallback to `EVAL` if the script
|
|
120
|
+
* cache is ever flushed.
|
|
99
121
|
*/
|
|
100
122
|
class RedisStore {
|
|
101
123
|
constructor(redis, options = {}) {
|
|
102
124
|
this.redis = redis;
|
|
103
125
|
this.prefix = options.keyPrefix ?? '';
|
|
126
|
+
redis.defineCommand('redeyeRecordFailure', { numberOfKeys: 1, lua: RECORD_FAILURE_SCRIPT });
|
|
127
|
+
redis.defineCommand('redeyeRecordOutcome', { numberOfKeys: 1, lua: RECORD_OUTCOME_SCRIPT });
|
|
128
|
+
redis.defineCommand('redeyeReleaseTrial', { numberOfKeys: 1, lua: RELEASE_TRIAL_SCRIPT });
|
|
104
129
|
}
|
|
105
130
|
async get(key) {
|
|
106
131
|
const raw = await this.redis.get(this.prefix + key);
|
|
@@ -115,16 +140,20 @@ class RedisStore {
|
|
|
115
140
|
await this.redis.del(this.prefix + key);
|
|
116
141
|
}
|
|
117
142
|
async recordFailureAtomic(key, opts) {
|
|
118
|
-
const raw =
|
|
143
|
+
const raw = await this.redis.redeyeRecordFailure(this.prefix + key, Math.max(1, Math.ceil(opts.ttlSeconds)), opts.failureThreshold, opts.now);
|
|
119
144
|
return JSON.parse(raw);
|
|
120
145
|
}
|
|
121
146
|
async recordOutcomeAtomic(key, opts) {
|
|
122
|
-
const raw =
|
|
147
|
+
const raw = await this.redis.redeyeRecordOutcome(this.prefix + key, opts.decay, opts.success ? 0 : 1, opts.minimumCalls, opts.errorRateThreshold, Math.max(1, Math.ceil(opts.ttlSeconds)), opts.now);
|
|
123
148
|
return JSON.parse(raw);
|
|
124
149
|
}
|
|
125
150
|
async claimTrial(key, ttlSeconds) {
|
|
126
|
-
const
|
|
127
|
-
|
|
151
|
+
const token = (0, node_crypto_1.randomUUID)();
|
|
152
|
+
const result = await this.redis.set(this.prefix + key, token, 'EX', Math.max(1, Math.ceil(ttlSeconds)), 'NX');
|
|
153
|
+
return result === 'OK' ? token : null;
|
|
154
|
+
}
|
|
155
|
+
async releaseTrial(key, token) {
|
|
156
|
+
await this.redis.redeyeReleaseTrial(this.prefix + key, token);
|
|
128
157
|
}
|
|
129
158
|
}
|
|
130
159
|
exports.RedisStore = RedisStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis-store.js","sourceRoot":"","sources":["../../src/stores/redis-store.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"redis-store.js","sourceRoot":"","sources":["../../src/stores/redis-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redeye-breaker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A circuit breaker for Node.js with an optional Redis-backed distributed mode, so breaker state can be shared across multiple app instances instead of being tracked per-process.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|