Lines
100.00%
23 / 23
Functions and Methods
100.00%
10 / 10
Classes and Traits
100.00%
1 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| RuntimeAdmin | 100.00% | 23 / 23 | 100.00% | 10 / 10 | 18 | 100.00% | 1 / 1 | |||
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| listHostedAppStatuses | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| requireAppStatus | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | |||||
| pauseApp | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 2 | |||||
| resumeApp | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 2 | |||||
| resetApp | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | |||||
| restartWorker | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 1 | |||||
| findChangeWarning | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| describeResetOutcome | 100.00% | 6 / 6 | 100.00% | 1 / 1 | 5 | |||||
| findResetWarning | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 3 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Stewart\Runtime\Admin; | |
| 6 | ||
| 7 | use Stewart\Contracts\App\AppId; | |
| 8 | use Stewart\Contracts\Exception\StoreException; | |
| 9 | use Stewart\Runtime\App\AppPauseOutcome; | |
| 10 | use Stewart\Runtime\App\AppPauseResetOutcome; | |
| 11 | use Stewart\Runtime\Broker\AppPauseService; | |
| 12 | use Stewart\Runtime\Broker\Collection\WorkerSlotCollection; | |
| 13 | use Stewart\Runtime\Broker\WorkerPool; | |
| 14 | use Stewart\Runtime\Broker\WorkerRestartOutcome; | |
| 15 | use Stewart\Runtime\Control\Assembler\AppStatusBuilder; | |
| 16 | use Stewart\Runtime\Control\Protocol\Frame\CommandResult; | |
| 17 | use Stewart\Runtime\Control\Protocol\Status\AppStatus; | |
| 18 | use Stewart\Runtime\Exception\AppException; | |
| 19 | use Stewart\Runtime\Exception\WorkerException; | |
| 20 | use Stewart\Runtime\Lifecycle\AppPauseOverridePersistence; | |
| 21 | use Stewart\Runtime\Lifecycle\AppPauseSource; | |
| 22 | use Stewart\Runtime\Lifecycle\AppStateAfterReset; | |
| 23 | ||
| 24 | final readonly class RuntimeAdmin | |
| 25 | { | |
| 26 | public function __construct( | |
| 27 | private AppPauseService $pauses, | |
| 28 | private AppStatusBuilder $appStatuses, | |
| 29 | private WorkerSlotCollection $workerSlots, | |
| 30 | private WorkerPool $pool, | |
| 31 | ) {} | |
| 32 | ||
| 33 | /** @return list<AppStatus> */ | |
| 34 | public function listHostedAppStatuses(): array | |
| 35 | { | |
| 36 | return $this->appStatuses->buildHostedAppStatuses(); | |
| 37 | } | |
| 38 | ||
| 39 | /** @throws AppException */ | |
| 40 | public function requireAppStatus(AppId $appId): AppStatus | |
| 41 | { | |
| 42 | $this->pauses->assertAppLoaded($appId); | |
| 43 | ||
| 44 | return $this->appStatuses->findAppStatus($appId) ?? throw AppException::unknown($appId); | |
| 45 | } | |
| 46 | ||
| 47 | /** @throws AppException */ | |
| 48 | public function pauseApp(AppId $appId, AppPauseSource $source): CommandResult | |
| 49 | { | |
| 50 | $outcome = $this->pauses->pauseApp($appId, $source); | |
| 51 | $message = \sprintf($outcome->changed ? 'App %s paused.' : 'App %s was already paused.', $appId); | |
| 52 | ||
| 53 | return new CommandResult($outcome->changed, $message, $this->findChangeWarning($outcome)); | |
| 54 | } | |
| 55 | ||
| 56 | /** @throws AppException */ | |
| 57 | public function resumeApp(AppId $appId, AppPauseSource $source): CommandResult | |
| 58 | { | |
| 59 | $outcome = $this->pauses->resumeApp($appId, $source); | |
| 60 | $message = \sprintf($outcome->changed ? 'App %s resumed.' : 'App %s was not paused.', $appId); | |
| 61 | ||
| 62 | return new CommandResult($outcome->changed, $message, $this->findChangeWarning($outcome)); | |
| 63 | } | |
| 64 | ||
| 65 | /** @throws AppException|StoreException */ | |
| 66 | public function resetApp(AppId $appId, AppPauseSource $source): CommandResult | |
| 67 | { | |
| 68 | $outcome = $this->pauses->resetApp($appId, $source); | |
| 69 | ||
| 70 | return new CommandResult($outcome->overrideRemoved, $this->describeResetOutcome($appId, $outcome), $this->findResetWarning($outcome)); | |
| 71 | } | |
| 72 | ||
| 73 | /** @throws WorkerException */ | |
| 74 | public function restartWorker(string $workerId): CommandResult | |
| 75 | { | |
| 76 | $slot = $this->workerSlots->requireSlotById($workerId); | |
| 77 | $outcome = $this->pool->restartWorker($slot); | |
| 78 | ||
| 79 | return new CommandResult($outcome === WorkerRestartOutcome::Begun, $outcome->describeForWorker($slot->workerId), null); | |
| 80 | } | |
| 81 | ||
| 82 | private function findChangeWarning(AppPauseOutcome $outcome): ?string | |
| 83 | { | |
| 84 | return $outcome->persistence->findWarning(); | |
| 85 | } | |
| 86 | ||
| 87 | private function describeResetOutcome(AppId $appId, AppPauseResetOutcome $outcome): string | |
| 88 | { | |
| 89 | if (!$outcome->overrideRemoved) { | |
| 90 | return \sprintf('App %s had no pause override.', $appId); | |
| 91 | } | |
| 92 | ||
| 93 | return \sprintf(match ($outcome->stateAfter) { | |
| 94 | AppStateAfterReset::PausedByConfig => 'App %s pause override removed; config keeps it paused.', | |
| 95 | AppStateAfterReset::Running => 'App %s pause override removed; it is running.', | |
| 96 | AppStateAfterReset::NotLoaded => 'App %s pause override removed.', | |
| 97 | }, $appId); | |
| 98 | } | |
| 99 | ||
| 100 | private function findResetWarning(AppPauseResetOutcome $outcome): ?string | |
| 101 | { | |
| 102 | return $outcome->overrideRemoved || $outcome->persistence !== AppPauseOverridePersistence::NotConfigured ? $outcome->persistence->findWarning() : null; | |
| 103 | } | |
| 104 | } |