- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
197 lines
5.4 KiB
PHP
197 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\ErrorBoundaries\CircuitBreaker;
|
|
|
|
use App\Framework\Core\ValueObjects\Timestamp;
|
|
use App\Framework\StateManagement\SerializableState;
|
|
|
|
/**
|
|
* Value object representing circuit breaker state for error boundaries
|
|
*/
|
|
final readonly class BoundaryCircuitBreakerState implements SerializableState
|
|
{
|
|
public function __construct(
|
|
public int $failureCount = 0,
|
|
public int $successCount = 0,
|
|
public ?Timestamp $lastFailureTime = null,
|
|
public ?Timestamp $openedAt = null,
|
|
public BoundaryCircuitState $state = BoundaryCircuitState::CLOSED,
|
|
public int $halfOpenAttempts = 0,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Check if circuit is open
|
|
*/
|
|
public function isOpen(): bool
|
|
{
|
|
return $this->state === BoundaryCircuitState::OPEN;
|
|
}
|
|
|
|
/**
|
|
* Check if circuit is closed
|
|
*/
|
|
public function isClosed(): bool
|
|
{
|
|
return $this->state === BoundaryCircuitState::CLOSED;
|
|
}
|
|
|
|
/**
|
|
* Check if circuit is half-open
|
|
*/
|
|
public function isHalfOpen(): bool
|
|
{
|
|
return $this->state === BoundaryCircuitState::HALF_OPEN;
|
|
}
|
|
|
|
/**
|
|
* Record a failure and return new state
|
|
*/
|
|
public function recordFailure(): self
|
|
{
|
|
return new self(
|
|
failureCount: $this->failureCount + 1,
|
|
successCount: $this->successCount,
|
|
lastFailureTime: Timestamp::now(),
|
|
openedAt: $this->openedAt,
|
|
state: $this->state,
|
|
halfOpenAttempts: $this->halfOpenAttempts,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record a success and return new state
|
|
*/
|
|
public function recordSuccess(): self
|
|
{
|
|
return new self(
|
|
failureCount: 0, // Reset failure count on success
|
|
successCount: $this->successCount + 1,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
openedAt: null, // Reset opened time
|
|
state: $this->state,
|
|
halfOpenAttempts: 0, // Reset half-open attempts
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Transition to OPEN state
|
|
*/
|
|
public function transitionToOpen(): self
|
|
{
|
|
return new self(
|
|
failureCount: $this->failureCount,
|
|
successCount: $this->successCount,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
openedAt: Timestamp::now(),
|
|
state: BoundaryCircuitState::OPEN,
|
|
halfOpenAttempts: 0,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Transition to HALF_OPEN state
|
|
*/
|
|
public function transitionToHalfOpen(): self
|
|
{
|
|
return new self(
|
|
failureCount: $this->failureCount,
|
|
successCount: $this->successCount,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
openedAt: $this->openedAt,
|
|
state: BoundaryCircuitState::HALF_OPEN,
|
|
halfOpenAttempts: 0,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Transition to CLOSED state
|
|
*/
|
|
public function transitionToClosed(): self
|
|
{
|
|
return new self(
|
|
failureCount: 0, // Reset failure count
|
|
successCount: $this->successCount,
|
|
lastFailureTime: null, // Reset last failure time
|
|
openedAt: null, // Reset opened time
|
|
state: BoundaryCircuitState::CLOSED,
|
|
halfOpenAttempts: 0,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Increment half-open attempts
|
|
*/
|
|
public function incrementHalfOpenAttempts(): self
|
|
{
|
|
return new self(
|
|
failureCount: $this->failureCount,
|
|
successCount: $this->successCount,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
openedAt: $this->openedAt,
|
|
state: $this->state,
|
|
halfOpenAttempts: $this->halfOpenAttempts + 1,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check if failure threshold is exceeded
|
|
*/
|
|
public function exceedsFailureThreshold(int $threshold): bool
|
|
{
|
|
return $this->failureCount >= $threshold;
|
|
}
|
|
|
|
/**
|
|
* Check if success threshold is met for half-open state
|
|
*/
|
|
public function meetsSuccessThreshold(int $threshold): bool
|
|
{
|
|
return $this->successCount >= $threshold;
|
|
}
|
|
|
|
/**
|
|
* Check if half-open attempts exceed maximum
|
|
*/
|
|
public function exceedsHalfOpenAttempts(int $maxAttempts): bool
|
|
{
|
|
return $this->halfOpenAttempts >= $maxAttempts;
|
|
}
|
|
|
|
/**
|
|
* Convert to array for serialization
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'failure_count' => $this->failureCount,
|
|
'success_count' => $this->successCount,
|
|
'last_failure_time' => $this->lastFailureTime?->toFloat(),
|
|
'opened_at' => $this->openedAt?->toFloat(),
|
|
'state' => $this->state->value,
|
|
'half_open_attempts' => $this->halfOpenAttempts,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Create from array (deserialization)
|
|
*/
|
|
public static function fromArray(array $data): static
|
|
{
|
|
return new self(
|
|
failureCount: $data['failure_count'] ?? 0,
|
|
successCount: $data['success_count'] ?? 0,
|
|
lastFailureTime: isset($data['last_failure_time'])
|
|
? Timestamp::fromFloat($data['last_failure_time'])
|
|
: null,
|
|
openedAt: isset($data['opened_at'])
|
|
? Timestamp::fromFloat($data['opened_at'])
|
|
: null,
|
|
state: BoundaryCircuitState::from($data['state'] ?? 'closed'),
|
|
halfOpenAttempts: $data['half_open_attempts'] ?? 0,
|
|
);
|
|
}
|
|
}
|