Files
Investidor-V2/app/Services/OpportunityTechnicalExecution.php
T

41 lines
1.8 KiB
PHP

<?php
namespace App\Services;
use App\Exceptions\OpportunityWorkflowUnavailable;
use App\Models\Opportunity;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Throwable;
/** Observe an already-authorized operation after its transaction unwinds. Never retry it. */
final class OpportunityTechnicalExecution
{
public function __construct(private OpportunityTechnicalIncidents $incidents) {}
/** @template T
* @param array<string,mixed> $input
* @param callable():T $operation
* @return T */
public function run(User $actor, Opportunity $before, string $action, array $input, callable $operation): mixed
{
try {
return $operation();
} catch (Throwable $failure) {
if ($failure instanceof ValidationException || $failure instanceof AuthorizationException || $failure instanceof AuthenticationException
|| $failure instanceof ModelNotFoundException || ($failure instanceof HttpExceptionInterface && $failure->getStatusCode() < 500)
|| ($failure instanceof HttpResponseException && $failure->getResponse()->getStatusCode() < 500)) {
throw $failure;
}
$etag = is_string($input['etag'] ?? null) && preg_match('/^[a-f0-9]{64}$/D', $input['etag']) === 1 ? $input['etag'] : '';
$incident = $this->incidents->record($actor, $before, $action, $etag, $failure);
throw new OpportunityWorkflowUnavailable($incident['reference'], $incident['recorded'], $failure);
}
}
}