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; 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)); } $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; } }