QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
CircuitBreakerState.cc
Go to the documentation of this file.
3
4CircuitBreakerState::CircuitBreakerState(const QString& stateName, QState* parent,
5 Action action, int failureThreshold,
6 int resetTimeoutMsecs)
7 : QGCState(stateName, parent)
8 , _action(std::move(action))
9 , _failureThreshold(failureThreshold)
10 , _resetTimeoutMsecs(resetTimeoutMsecs)
11{
12}
13
15{
16 _circuitState = State::Closed;
17 _failureCount = 0;
18 qCDebug(QGCStateMachineLog) << stateName() << "circuit breaker reset";
19 emit circuitReset();
20}
21
23{
24 // Check if we're in Open state and if reset timeout has passed
25 if (_circuitState == State::Open) {
26 if (_tripTimer.elapsed() >= _resetTimeoutMsecs) {
27 // Move to half-open to test recovery
28 _circuitState = State::HalfOpen;
29 qCDebug(QGCStateMachineLog) << stateName() << "circuit half-open, testing recovery";
30 } else {
31 // Still in cooldown, fail immediately
32 qCDebug(QGCStateMachineLog) << stateName() << "circuit open, failing fast ("
33 << (_resetTimeoutMsecs - _tripTimer.elapsed()) << "ms until retry)";
34 emit failed();
35 emit error();
36 return;
37 }
38 }
39
40 // Execute the action
41 qCDebug(QGCStateMachineLog) << stateName() << "executing action (state:"
42 << (_circuitState == State::HalfOpen ? "half-open" : "closed") << ")";
43
44 bool success = false;
45 if (_action) {
46 success = _action();
47 }
48
49 if (success) {
50 // Success - reset circuit if we were testing
51 if (_circuitState == State::HalfOpen) {
52 qCDebug(QGCStateMachineLog) << stateName() << "recovery successful, resetting circuit";
53 reset();
54 } else {
55 _failureCount = 0; // Reset failure count on success
56 }
57 emit succeeded();
58 emit advance();
59 } else {
60 // Failure
61 _failureCount++;
62 qCDebug(QGCStateMachineLog) << stateName() << "action failed, count:"
63 << _failureCount << "/" << _failureThreshold;
64
65 if (_circuitState == State::HalfOpen) {
66 // Failed during half-open test, go back to open
67 _circuitState = State::Open;
68 _tripTimer.restart();
69 qCDebug(QGCStateMachineLog) << stateName() << "half-open test failed, circuit re-opened";
70 } else if (_failureCount >= _failureThreshold) {
71 // Trip the circuit
72 _circuitState = State::Open;
73 _tripTimer.start();
74 qCDebug(QGCStateMachineLog) << stateName() << "failure threshold reached, circuit tripped";
75 emit tripped();
76 }
77
78 emit failed();
79 emit error();
80 }
81}
std::function< bool()> Action
void tripped()
Emitted when the circuit trips (too many failures)
void succeeded()
Emitted when action succeeds.
void failed()
Emitted when action fails (or circuit is open)
void reset()
Manually reset the circuit breaker.
void onEnter() override
Override to perform actions on state entry.
void circuitReset()
Emitted when the circuit resets (after successful half-open test)
CircuitBreakerState(const QString &stateName, QState *parent, Action action, int failureThreshold=5, int resetTimeoutMsecs=30000)
@ Closed
Normal operation.
@ Open
Tripped, failing fast.
@ HalfOpen
Testing if service recovered.
QString stateName() const