TenantAtlas/apps/platform/app/Support/OpsUx/ActiveRuns.php
Ahmed Darrazi a7df5c9adb
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 8m56s
chore: commit all changes (automated)
2026-05-04 14:09:40 +02:00

138 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\OpsUx;
use App\Models\OperationRun;
use App\Models\Tenant;
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('tenant_id', $tenantId)
->active()
->orderByDesc('created_at');
}
public static function shellVisibleQueryForTenantId(?int $tenantId): Builder
{
return OperationRun::query()
->where('tenant_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));
})
->orWhere(function (Builder $followUpQuery): void {
$followUpQuery->terminalFollowUp();
});
})
->orderByRaw(
'case when status in (?, ?) then 0 when status = ? and outcome in (?, ?, ?) then 1 when status = ? and outcome = ? then 2 else 3 end',
[
OperationRunStatus::Queued->value,
OperationRunStatus::Running->value,
OperationRunStatus::Completed->value,
OperationRunOutcome::Blocked->value,
OperationRunOutcome::PartiallySucceeded->value,
OperationRunOutcome::Failed->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(Tenant $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('tenant_id', $tenantId)
->healthyActive()
->exists();
}
public static function pollingIntervalForTenant(?Tenant $tenant): ?string
{
return $tenant instanceof Tenant
? self::pollingIntervalForTenantId((int) $tenant->getKey())
: null;
}
public static function pollingIntervalForTenantId(?int $tenantId): ?string
{
return self::existForTenantId($tenantId) ? '10s' : null;
}
}