Circuit Breaker
The resilience pattern that stops hammering a failing dependency: a deterministic CLOSED → OPEN → HALF_OPEN state machine driven by logical time.
Requirements
The breaker has three states — CLOSED (healthy, requests allowed), OPEN (tripped, requests blocked), and HALF_OPEN (probing, a trial request is allowed). It starts CLOSED with a consecutive-failure count of 0. Time is logical: every record and allow carries a timestamp, and timestamps are non-decreasing across the stream — never read a real clock.
allow(timestamp) — may this request proceed?
- CLOSED →
true. - OPEN → if
timestamp ≥ openedAt + Cthe cooldown has elapsed: transition to HALF_OPEN and returntrue(this is the trial request). Otherwise returnfalse. - HALF_OPEN →
true(the breaker is already probing).
record(success, timestamp) — report a request's outcome (success is 1 or 0):
- CLOSED → a success resets the consecutive-failure count to 0; a failure increments it, and when it reaches F the breaker trips to OPEN with
openedAt = timestamp. - HALF_OPEN → a success closes the breaker (→ CLOSED, failure count reset to 0); a failure re-opens it (→ OPEN,
openedAt = timestamp). - OPEN → ignored: no requests should be in flight while OPEN, so recorded outcomes do not change state. The breaker leaves OPEN only through a post-cooldown trial via
allow.
Only consecutive failures in CLOSED trip the breaker — a single success clears the count. The cooldown boundary is inclusive: a trial is permitted exactly at openedAt + C.
API to implement
Implement the class CircuitBreaker. The I/O driver is already written in the starter code — it parses the command script below and calls your methods. You only implement the class.
| Command | Returns | Behavior |
|---|---|---|
| record <success> <timestamp> | — | Report the outcome of a request at timestamp: success is 1 for success, 0 for failure. Updates the breaker's state per the rules below. |
| allow <timestamp> | boolean | Ask whether a request at timestamp may proceed. Returns true when the breaker is CLOSED, when it is OPEN but the cooldown has elapsed (which moves it to HALF_OPEN for a trial), or when it is already HALF_OPEN. Returns false while OPEN and still cooling down. |
Input format
The first line contains Q, the number of operations. The second line contains the constructor arguments: failureThreshold (F — consecutive failures that trip the breaker, ≥ 1) and cooldown (C — how long the breaker stays OPEN before a trial is allowed, ≥ 1). Each of the next Q lines is one command as listed above. String arguments contain no spaces.
Output format
For each command with a non-void return, print its result on its own line, in order. The driver does this for you — your methods just return values.
This is a design problem: the hidden tests exercise edge cases and interaction sequences, not performance tricks. Model the state cleanly and the tests will pass.
Sample cases
7
2 5
allow 0
record 0 0
record 0 1
allow 2
allow 6
record 1 7
allow 8true
false
true
true9
1 3
allow 0
record 0 0
allow 1
allow 3
record 0 3
allow 4
allow 6
record 1 6
allow 7true
false
true
false
true
true