mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-21 14:14:58 +00:00
Introduced a consistent LOG_PREFIX to all log messages in CancelStaleWorkflowHandler. This ensures clearer contextual identification in logs and improves traceability when debugging or monitoring workflow actions.
102 lines
3.9 KiB
PHP
102 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\MainBundle\Service\Workflow;
|
|
|
|
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
|
|
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\Clock\ClockInterface;
|
|
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
|
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
|
|
use Symfony\Component\Workflow\Metadata\MetadataStoreInterface;
|
|
use Symfony\Component\Workflow\Registry;
|
|
use Symfony\Component\Workflow\Transition;
|
|
|
|
#[AsMessageHandler]
|
|
final readonly class CancelStaleWorkflowHandler
|
|
{
|
|
private const LOG_PREFIX = '[CancelStaleWorkflowHandler] ';
|
|
|
|
public function __construct(
|
|
private EntityWorkflowRepository $workflowRepository,
|
|
private Registry $registry,
|
|
private EntityManagerInterface $em,
|
|
private LoggerInterface $logger,
|
|
private ClockInterface $clock,
|
|
) {}
|
|
|
|
public function __invoke(CancelStaleWorkflowMessage $message): void
|
|
{
|
|
$workflowId = $message->getWorkflowId();
|
|
$olderThanDate = $this->clock->now()->sub(new \DateInterval(CancelStaleWorkflowCronJob::KEEP_INTERVAL));
|
|
|
|
$workflow = $this->workflowRepository->find($message->getWorkflowId());
|
|
if (null === $workflow) {
|
|
$this->logger->alert(self::LOG_PREFIX.'Workflow was not found!', ['entityWorkflowId' => $workflowId]);
|
|
|
|
return;
|
|
}
|
|
|
|
if (false === $workflow->isStaledAt($olderThanDate)) {
|
|
$this->logger->alert(self::LOG_PREFIX.'Workflow has transitioned in the meantime.', ['entityWorkflowId' => $workflowId]);
|
|
|
|
throw new UnrecoverableMessageHandlingException('the workflow is not staled any more');
|
|
}
|
|
|
|
$workflowComponent = $this->registry->get($workflow, $workflow->getWorkflowName());
|
|
$metadataStore = $workflowComponent->getMetadataStore();
|
|
$transitions = $workflowComponent->getEnabledTransitions($workflow);
|
|
|
|
$transitionApplied = false;
|
|
$wasInInitialPosition = 'initial' === $workflow->getStep();
|
|
|
|
foreach ($transitions as $transition) {
|
|
if ($this->willTransitionLeadToFinalNegative($transition, $metadataStore)) {
|
|
$dto = new WorkflowTransitionContextDTO($workflow);
|
|
$workflowComponent->apply($workflow, $transition->getName(), [
|
|
'context' => $dto,
|
|
'byUser' => null,
|
|
'transitionAt' => $this->clock->now(),
|
|
'transition' => $transition->getName(),
|
|
]);
|
|
$this->logger->info(self::LOG_PREFIX.'EntityWorkflow has been cancelled automatically.', ['entityWorkflowId' => $workflowId]);
|
|
$transitionApplied = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$transitionApplied) {
|
|
$this->logger->error(self::LOG_PREFIX.'No valid transition found for EntityWorkflow.', ['entityWorkflowId' => $workflowId]);
|
|
throw new UnrecoverableMessageHandlingException(sprintf('No valid transition found for EntityWorkflow %d.', $workflowId));
|
|
}
|
|
|
|
if ($wasInInitialPosition) {
|
|
$this->em->remove($workflow);
|
|
}
|
|
|
|
$this->em->flush();
|
|
}
|
|
|
|
private function willTransitionLeadToFinalNegative(Transition $transition, MetadataStoreInterface $metadataStore): bool
|
|
{
|
|
foreach ($transition->getTos() as $place) {
|
|
$metadata = $metadataStore->getPlaceMetadata($place);
|
|
if (($metadata['isFinal'] ?? true) && false === ($metadata['isFinalPositive'] ?? true)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|