130 lines
4.8 KiB
PHP
130 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Temporal\SystemMonitor;
|
|
|
|
use Carbon\CarbonInterval;
|
|
use Temporal\Activity\ActivityOptions;
|
|
use Temporal\Common\RetryOptions;
|
|
use Temporal\Workflow;
|
|
|
|
class SystemMonitorWorkflow implements SystemMonitorWorkflowInterface
|
|
{
|
|
private bool $stopped = false;
|
|
private int $iteration = 0;
|
|
private int $totalIterations = 0;
|
|
private array $checkHistory = [];
|
|
private string $startedAt = '';
|
|
private string $lastCheckAt = '';
|
|
private float $healthScore = 100;
|
|
private string $status = 'initializing';
|
|
|
|
/** @var SystemMonitorActivityInterface */
|
|
private $activityStub;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->activityStub = Workflow::newActivityStub(
|
|
SystemMonitorActivityInterface::class,
|
|
ActivityOptions::new()
|
|
->withStartToCloseTimeout(CarbonInterval::seconds(60))
|
|
->withHeartbeatTimeout(CarbonInterval::seconds(15))
|
|
->withRetryOptions(
|
|
RetryOptions::new()->withMaximumAttempts(3)
|
|
)
|
|
);
|
|
}
|
|
|
|
public function monitor(int $intervalSeconds = 60, int $maxIterations = 30, array $state = [], array $simulationConfig = []): \Generator
|
|
{
|
|
// Restore state from previous Continue-As-New run, or initialize
|
|
if (!empty($state)) {
|
|
$this->iteration = $state['iteration'] ?? 0;
|
|
$this->totalIterations = $state['totalIterations'] ?? $maxIterations;
|
|
$this->checkHistory = $state['checkHistory'] ?? [];
|
|
$this->startedAt = $state['startedAt'] ?? Workflow::now()->format('c');
|
|
$this->healthScore = $state['healthScore'] ?? 100;
|
|
} else {
|
|
$this->totalIterations = $maxIterations;
|
|
$this->startedAt = Workflow::now()->format('c');
|
|
}
|
|
|
|
$this->status = 'monitoring';
|
|
|
|
try {
|
|
while ($this->iteration < $this->totalIterations && !$this->stopped) {
|
|
// Run health check activity
|
|
$result = yield $this->activityStub->runHealthCheck($simulationConfig);
|
|
|
|
// Store in check history (keep last 10)
|
|
$this->lastCheckAt = $result['timestamp'] ?? Workflow::now()->format('c');
|
|
$this->checkHistory[] = $result;
|
|
if (count($this->checkHistory) > 10) {
|
|
$this->checkHistory = array_slice($this->checkHistory, -10);
|
|
}
|
|
|
|
// Update health score (rolling average of last checks)
|
|
$scores = array_column($this->checkHistory, 'healthScore');
|
|
$this->healthScore = count($scores) > 0 ? round(array_sum($scores) / count($scores), 1) : 100;
|
|
|
|
$this->iteration++;
|
|
|
|
// Check if we should Continue-As-New
|
|
if (Workflow::getInfo()->shouldContinueAsNew || ($this->iteration % 15 === 0 && $this->iteration < $this->totalIterations)) {
|
|
$continueStub = Workflow::newContinueAsNewStub(SystemMonitorWorkflowInterface::class);
|
|
|
|
return yield $continueStub->monitor(
|
|
$intervalSeconds,
|
|
$this->totalIterations,
|
|
[
|
|
'iteration' => $this->iteration,
|
|
'totalIterations' => $this->totalIterations,
|
|
'checkHistory' => $this->checkHistory,
|
|
'startedAt' => $this->startedAt,
|
|
'healthScore' => $this->healthScore,
|
|
],
|
|
$simulationConfig
|
|
);
|
|
}
|
|
|
|
// Don't sleep after the last iteration or if stopped
|
|
if ($this->iteration < $this->totalIterations && !$this->stopped) {
|
|
yield Workflow::timer($intervalSeconds);
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$this->status = 'failed';
|
|
throw $e;
|
|
}
|
|
|
|
$this->status = $this->stopped ? 'stopped' : 'completed';
|
|
|
|
return [
|
|
'status' => $this->status,
|
|
'totalChecks' => $this->iteration,
|
|
'avgHealthScore' => $this->healthScore,
|
|
'lastCheckAt' => $this->lastCheckAt,
|
|
'startedAt' => $this->startedAt,
|
|
'checkHistory' => $this->checkHistory,
|
|
];
|
|
}
|
|
|
|
public function stop(): void
|
|
{
|
|
$this->stopped = true;
|
|
}
|
|
|
|
public function getStatus(): array
|
|
{
|
|
return [
|
|
'status' => $this->status,
|
|
'stopped' => $this->stopped,
|
|
'iteration' => $this->iteration,
|
|
'totalIterations' => $this->totalIterations,
|
|
'healthScore' => $this->healthScore,
|
|
'startedAt' => $this->startedAt,
|
|
'lastCheckAt' => $this->lastCheckAt,
|
|
'checkHistory' => $this->checkHistory,
|
|
];
|
|
}
|
|
}
|