-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement circuit breaker with closed/open/half-open states (#51)
- Add CircuitBreaker class in new network package with three states: CLOSED (requests pass), OPEN (requests blocked), HALF_OPEN (one probe) - Trips after 3 consecutive heartbeat failures, 10s cooldown before probe - Integrate into GameNetworkHandler: gates saveMove and sendHeartbeat - Connection UI reflects breaker state (Disconnected/Reconnecting/latency)
- Loading branch information
Francin Vincent
committed
Apr 6, 2026
1 parent
96800a0
commit defafb4
Showing
2 changed files
with
99 additions
and
5 deletions.
There are no files selected for viewing
77 changes: 77 additions & 0 deletions
77
core/src/main/java/com/group14/regicidechess/network/CircuitBreaker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package com.group14.regicidechess.network; | ||
|
|
||
| /** | ||
| * Simple circuit breaker with three states: CLOSED, OPEN, HALF_OPEN. | ||
| * | ||
| * CLOSED: All requests pass. Consecutive failures are counted. | ||
| * OPEN: Requests blocked. After cooldown, transitions to HALF_OPEN. | ||
| * HALF_OPEN: One probe request allowed. Success -> CLOSED, failure -> OPEN. | ||
| */ | ||
| public class CircuitBreaker { | ||
|
|
||
| public enum State { CLOSED, OPEN, HALF_OPEN } | ||
|
|
||
| private State state = State.CLOSED; | ||
| private int failureCount = 0; | ||
| private long openedAt = 0L; | ||
| private boolean halfOpenProbeUsed = false; | ||
|
|
||
| private final int failureThreshold; | ||
| private final long cooldownMs; | ||
|
|
||
| public CircuitBreaker(int failureThreshold, long cooldownMs) { | ||
| this.failureThreshold = failureThreshold; | ||
| this.cooldownMs = cooldownMs; | ||
| } | ||
|
|
||
| public synchronized boolean allowRequest() { | ||
| advanceIfCooldownElapsed(); | ||
| switch (state) { | ||
| case CLOSED: | ||
| return true; | ||
| case HALF_OPEN: | ||
| if (!halfOpenProbeUsed) { | ||
| halfOpenProbeUsed = true; | ||
| return true; | ||
| } | ||
| return false; | ||
| case OPEN: | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public synchronized void recordSuccess() { | ||
| failureCount = 0; | ||
| state = State.CLOSED; | ||
| halfOpenProbeUsed = false; | ||
| } | ||
|
|
||
| public synchronized void recordFailure() { | ||
| failureCount++; | ||
| if (state == State.HALF_OPEN || failureCount >= failureThreshold) { | ||
| state = State.OPEN; | ||
| openedAt = System.currentTimeMillis(); | ||
| halfOpenProbeUsed = false; | ||
| } | ||
| } | ||
|
|
||
| public synchronized State getState() { | ||
| advanceIfCooldownElapsed(); | ||
| return state; | ||
| } | ||
|
|
||
| public synchronized void reset() { | ||
| state = State.CLOSED; | ||
| failureCount = 0; | ||
| openedAt = 0L; | ||
| halfOpenProbeUsed = false; | ||
| } | ||
|
|
||
| private void advanceIfCooldownElapsed() { | ||
| if (state == State.OPEN && System.currentTimeMillis() - openedAt >= cooldownMs) { | ||
| state = State.HALF_OPEN; | ||
| halfOpenProbeUsed = false; | ||
| } | ||
| } | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters