TenantAtlas/apps/platform/app/Support/OpsUx/ActiveRuns.php
ahmido 564da05096 feat: implement operation run actionability system (#439)
This PR introduces the Operation Run Actionability System.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #439
2026-06-08 13:34:25 +00:00

131 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\OpsUx;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
final class ActiveRuns
{
private const int TERMINAL_SUCCESS_GRACE_SECONDS = 30;
public static function queryForTenantId(?int $tenantId): Builder
{
return OperationRun::query()
->where('managed_environment_id', $tenantId)
->active()
->orderByDesc('created_at');
}
public static function shellVisibleQueryForTenantId(?int $tenantId): Builder
{
return OperationRun::query()
->where('managed_environment_id', $tenantId)
->where(function (Builder $query): void {
$query
->where(function (Builder $activeQuery): void {
$activeQuery->active();
})
->orWhere(function (Builder $successQuery): void {
$successQuery
->where('status', OperationRunStatus::Completed->value)
->where('outcome', OperationRunOutcome::Succeeded->value)
->whereNotNull('completed_at')
->where('completed_at', '>=', now()->subSeconds(self::TERMINAL_SUCCESS_GRACE_SECONDS));
});
})
->orderByRaw(
'case when status in (?, ?) then 0 when status = ? and outcome = ? then 1 else 2 end',
[
OperationRunStatus::Queued->value,
OperationRunStatus::Running->value,
OperationRunStatus::Completed->value,
OperationRunOutcome::Succeeded->value,
],
)
->orderByRaw('coalesce(completed_at, started_at, created_at) desc')
->orderByDesc('id');
}
/**
* @return Collection<int, OperationRun>
*/
public static function visibleForTenantId(?int $tenantId, int $limit = 3): Collection
{
if (! is_int($tenantId) || $tenantId <= 0) {
return collect();
}
return self::queryForTenantId($tenantId)
->limit(max(1, $limit))
->get();
}
/**
* @return Collection<int, OperationRun>
*/
public static function shellVisibleForTenantId(?int $tenantId, int $limit = 3): Collection
{
if (! is_int($tenantId) || $tenantId <= 0) {
return collect();
}
return self::shellVisibleQueryForTenantId($tenantId)
->limit(max(1, $limit))
->get();
}
public static function countForTenantId(?int $tenantId): int
{
if (! is_int($tenantId) || $tenantId <= 0) {
return 0;
}
return self::queryForTenantId($tenantId)->count();
}
public static function shellVisibleCountForTenantId(?int $tenantId): int
{
if (! is_int($tenantId) || $tenantId <= 0) {
return 0;
}
return self::shellVisibleQueryForTenantId($tenantId)->count();
}
public static function existForTenant(ManagedEnvironment $tenant): bool
{
return self::existForTenantId((int) $tenant->getKey());
}
public static function existForTenantId(?int $tenantId): bool
{
if (! is_int($tenantId) || $tenantId <= 0) {
return false;
}
return OperationRun::query()
->where('managed_environment_id', $tenantId)
->healthyActive()
->exists();
}
public static function pollingIntervalForTenant(?ManagedEnvironment $tenant): ?string
{
return $tenant instanceof ManagedEnvironment
? self::pollingIntervalForTenantId((int) $tenant->getKey())
: null;
}
public static function pollingIntervalForTenantId(?int $tenantId): ?string
{
return self::existForTenantId($tenantId) ? '10s' : null;
}
}