/** * @param WorkflowMessage $workflowMessage * @return void */ public function handleWorkflowMessage(WorkflowMessage $workflowMessage) { if (!MessageNameUtils::isProcessingCommand($workflowMessage->messageName())) { $this->workflowEngine->dispatch(LogMessage::logUnsupportedMessageReceived($workflowMessage)); } try { if ($workflowMessage->messageType() === MessageNameUtils::COLLECT_DATA) { $processingMessage = $this->handleCollectData($workflowMessage); if (!$processingMessage instanceof ProcessingMessage) { throw new \RuntimeException(sprintf("%s::handleCollectData method returned %s instead of a ProcessingMessage", get_called_class(), is_object($processingMessage) ? get_class($processingMessage) : gettype($processingMessage))); } } else { if ($workflowMessage->messageType() === MessageNameUtils::PROCESS_DATA) { $processingMessage = $this->handleProcessData($workflowMessage); if (!$processingMessage instanceof ProcessingMessage) { throw new \RuntimeException(sprintf("%s::handleProcessData method returned %s instead of a ProcessingMessage", get_called_class(), is_object($processingMessage) ? get_class($processingMessage) : gettype($processingMessage))); } } else { $this->workflowEngine->dispatch(LogMessage::logUnsupportedMessageReceived($workflowMessage)); return; } } $this->workflowEngine->dispatch($processingMessage); return; } catch (\Exception $ex) { $this->workflowEngine->dispatch(LogMessage::logException($ex, $workflowMessage)); return; } }
/** * @inheritdoc */ public function dispatch($message, $sender = null) { if ($message instanceof RemoteMessage) { $message = $this->getToProcessingMessageTranslator()->translateToProcessingMessage($message); } if (!$message instanceof ProcessingMessage) { throw new \InvalidArgumentException(sprintf('Message can not be dispatched. Unknown type provided: %s', is_object($message) ? get_class($message) : gettype($message))); } $channelGetter = null; if (MessageNameUtils::isProcessingCommand($message->messageName())) { $channelGetter = "getCommandChannelFor"; } if (MessageNameUtils::isProcessingEvent($message->messageName())) { $channelGetter = "getEventChannelFor"; } if (MessageNameUtils::isProcessingLogMessage($message->messageName())) { $channelGetter = "getEventChannelFor"; } if (StartSubProcess::MSG_NAME === $message->messageName()) { $channelGetter = "getCommandChannelFor"; } if (SubProcessFinished::MSG_NAME === $message->messageName()) { $channelGetter = "getEventChannelFor"; } if (is_null($channelGetter)) { throw new \InvalidArgumentException(sprintf('Channel detection for message %s was not possible', $message->messageName())); } /** @var $channelBus CommandBus|EventBus */ $channelBus = $this->{$channelGetter}($message->target(), $message->origin(), $sender); $channelBus->dispatch($message); }
/** * @param Task $task * @param WorkflowMessage $message * @return bool */ private function isCorrectMessageFor(Task $task, WorkflowMessage $message) { if (MessageNameUtils::isProcessingCommand($message->messageName())) { if (!$task instanceof CollectData || $message->messageName() !== MessageNameUtils::getCollectDataCommandName($task->prototype()->of())) { return false; } } return true; }
/** * @throws \RuntimeException * @return RemoteMessage */ public function toServiceBusMessage() { $messageType = null; if (MessageNameUtils::isProcessingCommand($this->messageName())) { $messageType = MessageHeader::TYPE_COMMAND; } else { if (MessageNameUtils::isProcessingEvent($this->messageName())) { $messageType = MessageHeader::TYPE_EVENT; } else { throw new \RuntimeException(sprintf('Processing message %s can not be converted to service bus message. Type of the message could not be detected', $this->messageName())); } } $messageHeader = new MessageHeader($this->uuid(), $this->createdAt(), $this->version(), $messageType); $msgPayload = array('json' => json_encode($this->payload()), 'metadata' => $this->metadata, 'origin' => $this->origin(), 'target' => $this->target()); if ($this->processTaskListPosition()) { $msgPayload['processTaskListPosition'] = $this->processTaskListPosition()->toString(); } return new RemoteMessage($this->messageName(), $messageHeader, $msgPayload); }
/** * A Process can start or continue with the next step after it has received a message * * @param WorkflowMessage|LogMessage $message * @param WorkflowEngine $workflowEngine * @throws \RuntimeException * @return void */ public function receiveMessage($message, WorkflowEngine $workflowEngine) { if ($message instanceof WorkflowMessage) { if (MessageNameUtils::isProcessingCommand($message->messageName())) { $this->perform($workflowEngine, $message); return; } $this->assertTaskEntryExists($message->processTaskListPosition()); $this->recordThat(TaskEntryMarkedAsDone::at($message->processTaskListPosition())); $this->perform($workflowEngine, $message); return; } if ($message instanceof LogMessage) { $this->assertTaskEntryExists($message->processTaskListPosition()); $this->recordThat(LogMessageReceived::record($message)); if ($message->isError()) { $this->recordThat(TaskEntryMarkedAsFailed::at($message->processTaskListPosition())); } elseif ($this->isSubProcess() && $this->syncLogMessages) { //We only sync non error messages, because errors are always synced and then they would be received twice $messageForParent = $message->reconnectToProcessTask($this->parentTaskListPosition); $workflowEngine->dispatch($messageForParent); } } }
/** * @test */ public function it_detects_processing_messages_by_name() { $this->assertTrue(MessageNameUtils::isWorkflowMessage('processing-message-proophprocessingTestmockuserdictionary-collect-data')); $this->assertTrue(MessageNameUtils::isProcessingCommand('processing-message-proophprocessingTestmockuserdictionary-collect-data')); $this->assertFalse(MessageNameUtils::isProcessingEvent('processing-message-proophprocessingTestmockuserdictionary-collect-data')); $this->assertTrue(MessageNameUtils::isWorkflowMessage('processing-message-proophprocessingTestmockuserdictionary-data-collected')); $this->assertFalse(MessageNameUtils::isProcessingCommand('processing-message-proophprocessingTestmockuserdictionary-data-collected')); $this->assertTrue(MessageNameUtils::isProcessingEvent('processing-message-proophprocessingTestmockuserdictionary-data-collected')); $this->assertTrue(MessageNameUtils::isWorkflowMessage('processing-message-proophprocessingTestmockuserdictionary-process-data')); $this->assertTrue(MessageNameUtils::isProcessingCommand('processing-message-proophprocessingTestmockuserdictionary-process-data')); $this->assertFalse(MessageNameUtils::isProcessingEvent('processing-message-proophprocessingTesttypemockuserdictionary-process-data')); $this->assertTrue(MessageNameUtils::isWorkflowMessage('processing-message-proophprocessingTestmockuserdictionary-data-processed')); $this->assertFalse(MessageNameUtils::isProcessingCommand('processing-message-proophprocessingTestmockuserdictionary-data-processed')); $this->assertTrue(MessageNameUtils::isProcessingEvent('processing-message-proophprocessingTestmockuserdictionary-data-processed')); }