feat: Add ResetCircuitBreaker helper
This commit is contained in:
@@ -9,12 +9,24 @@ type Edge struct {
|
||||
Kind EdgeKind
|
||||
Duration int // travel time in seconds
|
||||
Transport string // transport type (train, plane, bus)
|
||||
TransportType string // deprecated: use Transport instead
|
||||
TransportType TransportType // transport type enum
|
||||
IsTransfer bool // whether this edge involves a transfer
|
||||
Departure string // ISO 8601 departure time
|
||||
Arrival string // ISO 8601 arrival time
|
||||
}
|
||||
|
||||
// TransportType represents the type of transport for an edge.
|
||||
type TransportType string
|
||||
|
||||
const (
|
||||
// TransportTypePlane represents airplane transport.
|
||||
TransportTypePlane TransportType = "plane"
|
||||
// TransportTypeTrain represents train transport.
|
||||
TransportTypeTrain TransportType = "train"
|
||||
// TransportTypeBus represents bus transport.
|
||||
TransportTypeBus TransportType = "bus"
|
||||
)
|
||||
|
||||
// NodeType represents the type of a graph node.
|
||||
type NodeType int
|
||||
|
||||
@@ -129,6 +141,7 @@ func BuildGraphFromStations(stations []StationInfo) *Graph {
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: "train",
|
||||
TransportType: TransportTypeTrain,
|
||||
IsTransfer: true,
|
||||
})
|
||||
|
||||
@@ -139,6 +152,7 @@ func BuildGraphFromStations(stations []StationInfo) *Graph {
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: "train",
|
||||
TransportType: TransportTypeTrain,
|
||||
IsTransfer: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -319,6 +319,19 @@ func newCircuitBreaker() *circuitBreaker {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ResetCircuitBreaker resets the circuit breaker to its initial closed state.
|
||||
// This is useful for testing or recovery scenarios where the circuit needs to be
|
||||
// manually reset without waiting for the timeout.
|
||||
func (cb *circuitBreaker) ResetCircuitBreaker() {
|
||||
cb.mu.Lock()
|
||||
defer cb.mu.Unlock()
|
||||
cb.state = closed
|
||||
cb.failures = 0
|
||||
cb.successes = 0
|
||||
cb.openSince = time.Time{}
|
||||
}
|
||||
|
||||
func (cb *circuitBreaker) allow() bool {
|
||||
cb.mu.Lock()
|
||||
defer cb.mu.Unlock()
|
||||
|
||||
@@ -307,6 +307,43 @@ func TestIsRetryableError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetCircuitBreaker(t *testing.T) {
|
||||
cb := newCircuitBreaker()
|
||||
|
||||
// Record failures to open the circuit
|
||||
cb.recordFailure()
|
||||
cb.recordFailure()
|
||||
cb.recordFailure()
|
||||
|
||||
if cb.state != open {
|
||||
t.Errorf("expected state open after 3 failures, got %v", cb.state)
|
||||
}
|
||||
|
||||
// Reset the circuit breaker
|
||||
cb.ResetCircuitBreaker()
|
||||
|
||||
// Should be back to closed state
|
||||
if cb.state != closed {
|
||||
t.Errorf("expected state closed after reset, got %v", cb.state)
|
||||
}
|
||||
if cb.failures != 0 {
|
||||
t.Errorf("expected failures to be 0 after reset, got %d", cb.failures)
|
||||
}
|
||||
if cb.successes != 0 {
|
||||
t.Errorf("expected successes to be 0 after reset, got %d", cb.successes)
|
||||
}
|
||||
if cb.openSince != (time.Time{}) {
|
||||
t.Errorf("expected openSince to be zero after reset, got %v", cb.openSince)
|
||||
}
|
||||
|
||||
// After reset, allow() should return true (circuit closed)
|
||||
for i := 0; i < 10; i++ {
|
||||
if !cb.allow() {
|
||||
t.Fatalf("expected allow() to return true after reset, attempt %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test Response parsing
|
||||
func TestResponseParsing(t *testing.T) {
|
||||
// Test with a valid JSON response
|
||||
|
||||
Reference in New Issue
Block a user