/**
  * @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);
 }
Example #3
0
 /**
  * @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;
 }
Example #4
0
 /**
  * @test
  */
 public function it_creates_process_with_process_data_task_from_data_collected_message()
 {
     $processDefinition = ["process_type" => Definition::PROCESS_LINEAR_MESSAGING, "tasks" => [["task_type" => Definition::TASK_PROCESS_DATA, "target" => 'test-target', "allowed_types" => ['Prooph\\ProcessingTest\\Mock\\TargetUserDictionary', 'Prooph\\ProcessingTest\\Mock\\AddressDictionary'], "preferred_type" => 'Prooph\\ProcessingTest\\Mock\\AddressDictionary']]];
     $wfMessage = $this->getUserDataCollectedTestMessage();
     $factory = new ProcessFactory([$wfMessage->messageName() => $processDefinition]);
     $process = $factory->deriveProcessFromMessage($wfMessage, NodeName::defaultName());
     $this->assertInstanceOf('Prooph\\Processing\\Processor\\LinearProcess', $process);
     $this->commandRouter->route(MessageNameUtils::getProcessDataCommandName('Prooph\\ProcessingTest\\Mock\\AddressDictionary'))->to($this->workflowMessageHandler);
     $process->perform($this->workflowEngine, $wfMessage);
     $receivedMessage = $this->workflowMessageHandler->lastWorkflowMessage();
     $this->assertEquals('Prooph\\ProcessingTest\\Mock\\AddressDictionary', $receivedMessage->payload()->getTypeClass());
 }
Example #5
0
 /**
  * @return string
  */
 public function messageName()
 {
     switch ($this->messageType()->toString()) {
         case MessageType::TYPE_DATA_PROCESSED:
             return MessageNameUtils::getDataProcessedEventName($this->processingType()->of());
         case MessageType::TYPE_PROCESS_DATA:
             return MessageNameUtils::getProcessDataCommandName($this->processingType()->of());
         case MessageType::TYPE_DATA_COLLECTED:
             return MessageNameUtils::getDataCollectedEventName($this->processingType()->of());
         case MessageType::TYPE_COLLECT_DATA:
             return MessageNameUtils::getCollectDataCommandName($this->processingType()->of());
     }
 }
 /**
  * @param $startMessage
  * @param array $processDefinition
  * @param array $knownProcessingTypes
  * @param ScriptLocation $scriptLocation
  * @return array
  */
 public static function translate($startMessage, array $processDefinition, array $knownProcessingTypes, ScriptLocation $scriptLocation)
 {
     $messageType = MessageNameUtils::getMessageSuffix($startMessage);
     foreach ($processDefinition['tasks'] as $i => &$task) {
         $task['id'] = $i;
     }
     return ['id' => $startMessage, 'name' => $processDefinition['name'], 'process_type' => $processDefinition['process_type'], 'start_message' => ['message_type' => $messageType, 'processing_type' => ProcessingTypeClass::extractFromMessageName($startMessage, $knownProcessingTypes)], 'tasks' => array_map(function ($task) use($scriptLocation) {
         if ($task['task_type'] === Definition::TASK_MANIPULATE_PAYLOAD) {
             $task['manipulation_script'] = str_replace($scriptLocation->toString() . DIRECTORY_SEPARATOR, "", $task['manipulation_script']);
         }
         return $task;
     }, $processDefinition['tasks'])];
 }
 /**
  * @param mixed $aHandler
  * @param mixed $aCommandOrEvent
  * @return bool
  */
 public function canInvoke($aHandler, $aCommandOrEvent)
 {
     if (!$aCommandOrEvent instanceof ProcessingMessage) {
         return false;
     }
     if (!$aHandler instanceof WorkflowMessageHandler) {
         return false;
     }
     if (!MessageNameUtils::isWorkflowMessage($aCommandOrEvent->messageName())) {
         return false;
     }
     return true;
 }
 public static function extractFromMessageName($messageName, array $knownProcessingTypes)
 {
     if (!is_string($messageName)) {
         throw new \InvalidArgumentException("Message name must be string");
     }
     $processingType = MessageNameUtils::getTypePartOfMessageName($messageName);
     if (empty($processingType)) {
         throw new \InvalidArgumentException(sprintf("Invalid message name -%s- provided. Data type declaration could not be found.", $messageName));
     }
     foreach ($knownProcessingTypes as $knownProcessingType) {
         if (MessageNameUtils::normalize($knownProcessingType) === $processingType) {
             return $knownProcessingType;
         }
     }
     throw new \InvalidArgumentException(sprintf("The data type %s can not be resolved to a known class: %s", $processingType, implode(", ", $knownProcessingTypes)));
 }
 /**
  * @param RemoteMessage $message
  * @return LogMessage|WorkflowMessage|StartSubProcess|SubProcessFinished
  * @throws \InvalidArgumentException
  */
 public function translateToProcessingMessage(RemoteMessage $message)
 {
     if (MessageNameUtils::isWorkflowMessage($message->name())) {
         return WorkflowMessage::fromServiceBusMessage($message);
     } else {
         if (MessageNameUtils::isProcessingLogMessage($message->name())) {
             return LogMessage::fromServiceBusMessage($message);
         } else {
             if (StartSubProcess::MSG_NAME === $message->name()) {
                 return StartSubProcess::fromServiceBusMessage($message);
             } else {
                 if (SubProcessFinished::MSG_NAME === $message->name()) {
                     return SubProcessFinished::fromServiceBusMessage($message);
                 }
             }
         }
     }
     throw new \InvalidArgumentException(sprintf('Message with name %s can not be translated. Unknown type provided.', $message->name()));
 }
Example #10
0
 protected function setUpOtherMachine()
 {
     $this->otherMachineWorkflowMessageHandler = new TestWorkflowMessageHandler();
     $commandBus = new CommandBus();
     $this->otherMachineCommandRouter = new CommandRouter();
     $this->otherMachineCommandRouter->route(MessageNameUtils::getCollectDataCommandName('Prooph\\ProcessingTest\\Mock\\UserDictionaryS2'))->to($this->otherMachineWorkflowMessageHandler);
     $this->otherMachineCommandRouter->route(MessageNameUtils::getProcessDataCommandName('Prooph\\ProcessingTest\\Mock\\TargetUserDictionary'))->to($this->otherMachineWorkflowMessageHandler);
     $commandBus->utilize($this->otherMachineCommandRouter);
     $commandBus->utilize(new HandleWorkflowMessageInvokeStrategy());
     $commandBus->utilize(new WorkflowProcessorInvokeStrategy());
     $commandBus->utilize(new ToProcessingMessageTranslator());
     $this->otherMachineWorkflowEngine = new RegistryWorkflowEngine();
     $this->otherMachineWorkflowEngine->registerCommandBus($commandBus, ['test-case', 'test-target', 'other_machine']);
     //Add second command bus to local workflow engine to forward StartSubProcess command to message dispatcher
     $this->otherMachineMessageDispatcher = new InMemoryRemoteMessageDispatcher($commandBus, new EventBus());
     $parentNodeCommandBus = new CommandBus();
     $parentCommandRouter = new CommandRouter();
     $parentCommandRouter->route(StartSubProcess::MSG_NAME)->to($this->otherMachineMessageDispatcher);
     $parentNodeCommandBus->utilize($parentCommandRouter);
     $parentNodeCommandBus->utilize(new ForwardToRemoteMessageDispatcherStrategy(new FromProcessingMessageTranslator()));
     $this->workflowEngine->registerCommandBus($parentNodeCommandBus, ['other_machine']);
     $this->getOtherMachineWorkflowProcessor();
     //Add event buses to handle SubProcessFinished event
     $parentNodeEventBus = new EventBus();
     $parentNodeEventRouter = new EventRouter();
     $parentNodeEventBus->utilize(new SingleTargetMessageRouter($this->getTestWorkflowProcessor()));
     $parentNodeEventBus->utilize(new ToProcessingMessageTranslator());
     $parentNodeEventBus->utilize(new WorkflowProcessorInvokeStrategy());
     $otherMachineEventBus = new EventBus();
     $toParentNodeMessageDispatcher = new InMemoryRemoteMessageDispatcher(new CommandBus(), $parentNodeEventBus);
     $otherMachineEventBus->utilize(new SingleTargetMessageRouter($toParentNodeMessageDispatcher));
     $otherMachineEventBus->utilize(new ForwardToRemoteMessageDispatcherStrategy(new FromProcessingMessageTranslator()));
     $this->otherMachineWorkflowEngine->registerEventBus($otherMachineEventBus, [Definition::DEFAULT_NODE_NAME]);
 }
Example #11
0
 /**
  * @return WorkflowMessage|LogMessage
  * @throws \RuntimeException
  */
 public function lastMessage()
 {
     $sbMessage = RemoteMessage::fromArray($this->payload['last_message']);
     if (MessageNameUtils::isProcessingLogMessage($sbMessage->name())) {
         return LogMessage::fromServiceBusMessage($sbMessage);
     }
     if (MessageNameUtils::isWorkflowMessage($sbMessage->name())) {
         return WorkflowMessage::fromServiceBusMessage($sbMessage);
     }
     throw new \RuntimeException(sprintf("Sub process %s has received last a message with name %s that has no known message format", $this->processorNodeName() . '::' . $this->subProcessId(), $sbMessage->name()));
 }
Example #12
0
 /**
  * @test
  */
 public function it_sets_wf_message_target_to_target_defined_in_the_process_task()
 {
     $task = ProcessData::address('test-target', ['Prooph\\ProcessingTest\\Mock\\TargetUserDictionary']);
     $process = LinearProcess::setUp(NodeName::defaultName(), [$task]);
     $wfm = WorkflowMessage::collectDataOf(UserDictionary::prototype(), 'test-case', NodeName::defaultName());
     $answer = $wfm->answerWith(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]));
     $this->commandRouter->route(MessageNameUtils::getProcessDataCommandName('Prooph\\ProcessingTest\\Mock\\TargetUserDictionary'))->to($this->workflowMessageHandler);
     $process->perform($this->workflowEngine, $answer);
     $receivedMessage = $this->workflowMessageHandler->lastWorkflowMessage();
     $this->assertEquals('test-target', $receivedMessage->target());
 }
Example #13
0
 /**
  * @param ManipulatePayload $task
  * @param TaskListPosition $taskListPosition
  * @param WorkflowEngine $workflowEngine
  * @param WorkflowMessage $previousMessage
  */
 protected function performManipulatePayload(ManipulatePayload $task, TaskListPosition $taskListPosition, WorkflowEngine $workflowEngine, WorkflowMessage $previousMessage)
 {
     if (!MessageNameUtils::isProcessingEvent($previousMessage->messageName())) {
         $this->receiveMessage(LogMessage::logWrongMessageReceivedFor($task, $taskListPosition, $previousMessage), $workflowEngine);
         return;
     }
     $payload = $previousMessage->payload();
     try {
         $task->performManipulationOn($payload);
     } catch (\Exception $ex) {
         $this->receiveMessage(LogMessage::logException($ex, $taskListPosition), $workflowEngine);
         return;
     }
     $newEvent = $previousMessage->prepareDataProcessing($taskListPosition, $this->taskList->taskListId()->nodeName())->answerWithDataProcessingCompleted();
     $this->receiveMessage($newEvent, $workflowEngine);
 }
Example #14
0
 /**
  * Start or continue the process with the help of given WorkflowEngine and optionally with given WorkflowMessage
  *
  * @param WorkflowEngine $workflowEngine
  * @param WorkflowMessage $workflowMessage
  * @throws \RuntimeException
  * @throws \BadMethodCallException
  * @return void
  */
 public function perform(WorkflowEngine $workflowEngine, WorkflowMessage $workflowMessage = null)
 {
     $taskListEntry = $this->taskList->getNextNotStartedTaskListEntry();
     if (is_null($taskListEntry)) {
         throw new \RuntimeException('ForEachProcess::perform was called but there are no tasks configured!');
     }
     if (is_null($workflowMessage)) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logNoMessageReceivedFor($taskListEntry->task(), $taskListEntry->taskListPosition()), $workflowEngine);
         return;
     }
     $workflowMessage = $workflowMessage->reconnectToProcessTask($taskListEntry->taskListPosition());
     if (count($this->taskList->getAllTaskListEntries()) > 1) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logErrorMsg('The ForEachProcess can only handle a single RunSubProcess task but there are more tasks configured', $workflowMessage), $workflowEngine);
         return;
     }
     if (!$taskListEntry->task() instanceof RunSubProcess) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logErrorMsg(sprintf('The ForEachProcess can only handle a RunSubProcess task but there is a %s task configured', get_class($taskListEntry->task())), $workflowMessage), $workflowEngine);
         return;
     }
     if (!MessageNameUtils::isProcessingEvent($workflowMessage->messageName())) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logWrongMessageReceivedFor($taskListEntry->task(), $taskListEntry->taskListPosition(), $workflowMessage), $workflowEngine);
         return;
     }
     $collection = $workflowMessage->payload()->toType();
     if (!$collection instanceof CollectionType) {
         $this->receiveMessage(LogMessage::logErrorMsg(sprintf('The ForEachProcess requires a Prooph\\ProcessingType\\CollectionType as payload of the incoming message, but it is a %s type given', $workflowMessage->payload()->getTypeClass()), $workflowMessage), $workflowEngine);
         return;
     }
     $this->startSubProcessForEachItem($collection, $workflowEngine);
 }
Example #15
0
 /**
  * @param string $messageName
  * @param array $availableProcessingTypes
  * @throws \InvalidArgumentException
  */
 private function assertMessageName($messageName, array $availableProcessingTypes)
 {
     if (!is_string($messageName)) {
         throw new \InvalidArgumentException('Message name must be a string');
     }
     if (!MessageNameUtils::isWorkflowMessage($messageName)) {
         throw new \InvalidArgumentException(sprintf('Message name format -%s- is not valid', $messageName));
     }
     ProcessingTypeClass::extractFromMessageName($messageName, $availableProcessingTypes);
 }
Example #16
0
/**
 * The workflow engine provides access to the communication layer of the processing system.
 * Communication is based on ProophServiceBus. We use the idea of CQRS to decouple the
 * workflow processor from workflow message handlers which are responsible for processing
 * single tasks. A workflow message handler is normally the glue component which connects
 * Prooph\Processing with an external system. It receives commands from the processor like collect data or
 * process data and send events back to tell the processor what's happened.
 *
 * Each target (external system) gets a command bus and an event bus assigned. These are the communication
 * channels between the processor and the target.
 * You can use the full power of ProophServiceBus so a channel can be a local bus, a link to a messaging infrastructure,
 * a link to a worker queue, or a http remote interface.
 *
 * @return \Prooph\Processing\Processor\RegistryWorkflowEngine
 */
function _set_up_workflow_engine()
{
    $commandBus = new \Prooph\ServiceBus\CommandBus();
    $eventBus = new \Prooph\ServiceBus\EventBus();
    $commandRouter = new \Prooph\ServiceBus\Router\CommandRouter();
    //For our scenario it is enough to use a closure as workflow message handler
    //In a production system this should be a class loadable by Zend\ServiceManager
    //See the more complex scenarios to get an idea how such a set up can be look like.
    $commandRouter->route(\Prooph\Processing\Message\MessageNameUtils::getProcessDataCommandName('Prooph\\ProcessingExample\\Type\\SourceUser'))->to(function (\Prooph\Processing\Message\WorkflowMessage $message) use($eventBus) {
        $dataAsJsonString = json_encode($message->payload());
        $answer = $message->answerWithDataProcessingCompleted();
        try {
            \Zend\Stdlib\ErrorHandler::start();
            if (!file_put_contents('data/target-data.txt', $dataAsJsonString)) {
                \Zend\Stdlib\ErrorHandler::stop(true);
            }
        } catch (\Exception $ex) {
            $answer = \Prooph\Processing\Message\LogMessage::logException($ex, $message);
        }
        $eventBus->dispatch($answer);
    });
    $commandBus->utilize($commandRouter);
    $commandBus->utilize(new \Prooph\ServiceBus\InvokeStrategy\CallbackStrategy());
    $workflowEngine = new \Prooph\Processing\Processor\RegistryWorkflowEngine();
    $workflowEngine->registerCommandBus($commandBus, ['target-file-writer']);
    $workflowEngine->registerEventBus($eventBus, [\Prooph\Processing\Processor\Definition::SERVICE_WORKFLOW_PROCESSOR]);
    return $workflowEngine;
}
Example #17
0
 /**
  * Start or continue the process with the help of given WorkflowEngine and optionally with given WorkflowMessage
  *
  * @param WorkflowEngine $workflowEngine
  * @param WorkflowMessage $workflowMessage
  * @throws \RuntimeException
  * @return void
  */
 public function perform(WorkflowEngine $workflowEngine, WorkflowMessage $workflowMessage = null)
 {
     $taskListEntry = $this->taskList->getNextNotStartedTaskListEntry();
     if (is_null($taskListEntry)) {
         throw new \RuntimeException('ChunkProcess::perform was called but there are no tasks configured!');
     }
     if (is_null($workflowMessage)) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logNoMessageReceivedFor($taskListEntry->task(), $taskListEntry->taskListPosition()), $workflowEngine);
         return;
     }
     $workflowMessage = $workflowMessage->reconnectToProcessTask($taskListEntry->taskListPosition());
     if (count($this->taskList->getAllTaskListEntries()) > 1) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->logErrorMsg('The ChunkProcess can only handle a single RunSubProcess task but there are more tasks configured', $workflowMessage, $workflowEngine);
         return;
     }
     if (!$taskListEntry->task() instanceof RunSubProcess) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->logErrorMsg(sprintf('The ChunkProcess can only handle a RunSubProcess task but there is a %s task configured', get_class($taskListEntry->task())), $workflowMessage, $workflowEngine);
         return;
     }
     if (!MessageNameUtils::isProcessingEvent($workflowMessage->messageName())) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $this->receiveMessage(LogMessage::logWrongMessageReceivedFor($taskListEntry->task(), $taskListEntry->taskListPosition(), $workflowMessage), $workflowEngine);
         return;
     }
     $collection = $workflowMessage->payload()->toType();
     if (!$collection instanceof CollectionType) {
         $this->logErrorMsg(sprintf('The ChunkProcess requires a Prooph\\ProcessingType\\CollectionType as payload of the incoming message, but it is a %s type given', $workflowMessage->payload()->getTypeClass()), $workflowMessage, $workflowEngine);
         return;
     }
     $metadata = $workflowMessage->metadata();
     if (!isset($metadata[self::META_OFFSET])) {
         $this->logErrorMsg('The ChunkProcess requires a offset key in the message metadata.', $workflowMessage, $workflowEngine);
         return;
     }
     if ((int) $metadata[self::META_OFFSET] !== 0) {
         $this->logErrorMsg('The ChunkProcess requires that the first chunk starts with a offset of 0.', $workflowMessage, $workflowEngine);
         return;
     }
     if (!isset($metadata[self::META_LIMIT])) {
         $this->logErrorMsg('The ChunkProcess requires a limit key in the message metadata.', $workflowMessage, $workflowEngine);
         return;
     }
     if ((int) $metadata[self::META_LIMIT] <= 0) {
         $this->logErrorMsg('The ChunkProcess requires that metadata.limit is greater than 0.', $workflowMessage, $workflowEngine);
         return;
     }
     if (!isset($metadata[self::META_TOTAL_ITEMS])) {
         $this->logErrorMsg('The ChunkProcess requires a total_items key in the message metadata.', $workflowMessage, $workflowEngine);
         return;
     }
     $this->startSubProcessForEachChunk($workflowMessage, $workflowEngine);
 }
Example #18
0
 /**
  * @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);
 }
 /**
  * @test
  */
 public function it_detects_processing_log_message_by_name()
 {
     $this->assertTrue(MessageNameUtils::isProcessingLogMessage(MessageNameUtils::LOG_MESSAGE_NAME));
     $this->assertFalse(MessageNameUtils::isProcessingLogMessage('processing-message-proophprocessingTestmockuserdictionary-process-data'));
 }