/**
  * @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;
     }
 }
Ejemplo n.º 2
0
 /**
  * @param WorkflowEngine $workflowEngine
  */
 protected function startWithoutMessage(WorkflowEngine $workflowEngine)
 {
     $taskListEntry = $this->taskList->getNextNotStartedTaskListEntry();
     if ($taskListEntry) {
         $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition()));
         $task = $taskListEntry->task();
         if (!$task instanceof CollectData && !$task instanceof RunSubProcess) {
             $this->receiveMessage(LogMessage::logNoMessageReceivedFor($task, $taskListEntry->taskListPosition()), $workflowEngine);
             return;
         }
         $this->performTask($task, $taskListEntry->taskListPosition(), $workflowEngine);
     }
 }
Ejemplo n.º 3
0
 /**
  * If workflow message handler receives a collect-data message it forwards the message to this
  * method and uses the returned ProcessingMessage as response
  *
  * @param WorkflowMessage $workflowMessage
  * @return ProcessingMessage
  */
 protected function handleCollectData(WorkflowMessage $workflowMessage)
 {
     if ($workflowMessage->payload()->getTypeClass() === 'Prooph\\ProcessingExample\\Type\\SourceUser') {
         $userData = (include __DIR__ . '/../../data/user-source-data.php');
         if (!$userData) {
             return LogMessage::logErrorMsg("Could not read user data from examples/data/user-source-data.php. Please check the permissions", $workflowMessage);
         }
         $sourceUser = SourceUser::fromNativeValue($userData);
         return $workflowMessage->answerWith($sourceUser);
     } else {
         return LogMessage::logErrorMsg(sprintf('%s: Unknown type %s received', __CLASS__, $workflowMessage->payload()->getTypeClass()), $workflowMessage);
     }
 }
Ejemplo n.º 4
0
 /**
  * If workflow message handler receives a process-data message it forwards the message to this
  * method and uses the returned ProcessingMessage as response
  *
  * @param WorkflowMessage $workflowMessage
  * @return ProcessingMessage
  */
 protected function handleProcessData(WorkflowMessage $workflowMessage)
 {
     if (array_key_exists($workflowMessage->payload()->getTypeClass(), $this->getSupportedMessagesByTypeMap())) {
         $dataAsJsonString = json_encode($workflowMessage->payload());
         $answer = $workflowMessage->answerWithDataProcessingCompleted();
         try {
             \Zend\Stdlib\ErrorHandler::start();
             if (!file_put_contents(__DIR__ . '/../../data/target-data.txt', $dataAsJsonString)) {
                 \Zend\Stdlib\ErrorHandler::stop(true);
             }
         } catch (\Exception $ex) {
             $answer = \Prooph\Processing\Message\LogMessage::logException($ex, $workflowMessage);
         }
         return $answer;
     } else {
         return LogMessage::logErrorMsg(sprintf('%s: Unknown type %s received', __CLASS__, $workflowMessage->payload()->getTypeClass()), $workflowMessage);
     }
 }
 /**
  * @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()));
 }
 public function provideMessages()
 {
     $localTaskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1);
     $remoteTaskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::fromString("remote-system"), ProcessId::generate()), 1);
     $wfMessageWithoutTaskListPosition = WorkflowMessage::collectDataOf(TestUser::prototype(), 'test-case', 'localhost');
     $expectedDataWfMessageWithoutTaskListPosition = ['message_id' => $wfMessageWithoutTaskListPosition->uuid()->toString(), 'message_name' => $wfMessageWithoutTaskListPosition->messageName(), 'version' => $wfMessageWithoutTaskListPosition->version(), 'task_list_position' => null, 'process_id' => null, 'status' => MessageStatus::PENDING, 'failure_msg' => null];
     $wfMessageWithTaskListPosition = WorkflowMessage::collectDataOf(TestUser::prototype(), 'test-case', 'localhost');
     $wfMessageWithTaskListPosition->connectToProcessTask($localTaskListPosition);
     $expectedDataWfMessageWithTaskListPosition = ['message_id' => $wfMessageWithTaskListPosition->uuid()->toString(), 'message_name' => $wfMessageWithTaskListPosition->messageName(), 'version' => $wfMessageWithTaskListPosition->version(), 'task_list_position' => $wfMessageWithTaskListPosition->processTaskListPosition()->toString(), 'process_id' => $wfMessageWithTaskListPosition->processTaskListPosition()->taskListId()->processId()->toString(), 'status' => MessageStatus::PENDING, 'failure_msg' => null];
     $logMessage = LogMessage::logDebugMsg("Log message", $wfMessageWithTaskListPosition);
     $expectedDataLogMessage = ['message_id' => $logMessage->uuid()->toString(), 'message_name' => $logMessage->messageName(), 'version' => 1, 'task_list_position' => $logMessage->processTaskListPosition()->toString(), 'process_id' => $logMessage->processTaskListPosition()->taskListId()->processId()->toString(), 'status' => MessageStatus::PENDING, 'failure_msg' => null];
     $startSubProcess = StartSubProcess::at($localTaskListPosition, ["process_type" => "faked"], false, "remote-system");
     $expectedDataStartSubProcess = ['message_id' => $startSubProcess->uuid()->toString(), 'message_name' => $startSubProcess->messageName(), 'version' => $startSubProcess->version(), 'task_list_position' => $startSubProcess->parentTaskListPosition()->toString(), 'process_id' => $startSubProcess->parentTaskListPosition()->taskListId()->processId()->toString(), 'status' => MessageStatus::PENDING, 'failure_msg' => null];
     $wfMessageWithRemoteTaskListPosition = WorkflowMessage::collectDataOf(TestUser::prototype(), 'test-case', 'localhost');
     $wfMessageWithRemoteTaskListPosition->connectToProcessTask($remoteTaskListPosition);
     $logMessageSubProcess = LogMessage::logErrorMsg("Faked error", $wfMessageWithRemoteTaskListPosition);
     $subProcessFinished = SubProcessFinished::record(NodeName::fromString("remote-system"), $remoteTaskListPosition->taskListId()->processId(), false, $logMessageSubProcess, $localTaskListPosition);
     $expectedDataSubProcessFinished = ['message_id' => $subProcessFinished->uuid()->toString(), 'message_name' => $subProcessFinished->messageName(), 'version' => $subProcessFinished->version(), 'task_list_position' => $logMessageSubProcess->processTaskListPosition()->toString(), 'process_id' => $logMessageSubProcess->processTaskListPosition()->taskListId()->processId()->toString(), 'status' => MessageStatus::PENDING, 'failure_msg' => null];
     return [[$wfMessageWithoutTaskListPosition, $expectedDataWfMessageWithoutTaskListPosition], [$wfMessageWithoutTaskListPosition->toServiceBusMessage(), $expectedDataWfMessageWithoutTaskListPosition], [$wfMessageWithTaskListPosition, $expectedDataWfMessageWithTaskListPosition], [$wfMessageWithTaskListPosition->toServiceBusMessage(), $expectedDataWfMessageWithTaskListPosition], [$logMessage, $expectedDataLogMessage], [$logMessage->toServiceBusMessage(), $expectedDataLogMessage], [$startSubProcess, $expectedDataStartSubProcess], [$startSubProcess->toServiceBusMessage(), $expectedDataStartSubProcess], [$subProcessFinished, $expectedDataSubProcessFinished], [$subProcessFinished->toServiceBusMessage(), $expectedDataSubProcessFinished]];
 }
Ejemplo n.º 7
0
 /**
  * @test
  */
 public function it_translates_to_service_bus_message_and_back()
 {
     $nodeName = NodeName::fromString('other_machine');
     $subProcessId = ProcessId::generate();
     $parentTaskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1);
     $wfMessage = $this->getUserDataCollectedTestMessage();
     $wfMessage->connectToProcessTask(TaskListPosition::at(TaskListId::linkWith($nodeName, $subProcessId), 1));
     $message = LogMessage::logDebugMsg("Processing finished", $wfMessage);
     $event = SubProcessFinished::record($nodeName, $subProcessId, true, $message, $parentTaskListPosition);
     $sbMessage = $event->toServiceBusMessage();
     $this->assertInstanceOf('Prooph\\Common\\Messaging\\RemoteMessage', $sbMessage);
     $copyOfEvent = SubProcessFinished::fromServiceBusMessage($sbMessage);
     $this->assertInstanceOf('Prooph\\Processing\\Processor\\Event\\SubProcessFinished', $copyOfEvent);
     $this->assertTrue($nodeName->equals($copyOfEvent->processorNodeName()));
     $this->assertTrue($parentTaskListPosition->equals($copyOfEvent->parentTaskListPosition()));
     $this->assertEquals($parentTaskListPosition->taskListId()->nodeName()->toString(), $copyOfEvent->target());
     $this->assertTrue($subProcessId->equals($copyOfEvent->subProcessId()));
     $this->assertTrue($copyOfEvent->succeed());
     $this->assertEquals($message->technicalMsg(), $copyOfEvent->lastMessage()->technicalMsg());
 }
 /**
  * @test
  */
 public function it_sends_a_sub_process_finished_event_via_message_dispatcher_to_a_handler()
 {
     $taskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1);
     $wfMessage = $this->getUserDataCollectedTestMessage();
     $wfMessage->connectToProcessTask($taskListPosition);
     $logMessage = LogMessage::logDebugMsg("Just a fake event", $wfMessage);
     $subProcessFinished = SubProcessFinished::record(NodeName::defaultName(), $taskListPosition->taskListId()->processId(), true, $logMessage, $taskListPosition);
     $eventBus = new EventBus();
     $eventRouter = new EventRouter();
     $eventRouter->route(SubProcessFinished::MSG_NAME)->to($this->messageDispatcher);
     $eventBus->utilize($eventRouter);
     $eventBus->utilize(new ForwardToRemoteMessageDispatcherStrategy(new FromProcessingMessageTranslator()));
     $eventBus->dispatch($subProcessFinished);
     /** @var $receivedMessage SubProcessFinished */
     $receivedMessage = $this->receivedMessage;
     $this->assertInstanceOf(get_class($subProcessFinished), $receivedMessage);
     $this->assertTrue($taskListPosition->taskListId()->processId()->equals($receivedMessage->subProcessId()));
     $this->assertTrue($taskListPosition->equals($receivedMessage->parentTaskListPosition()));
     $this->assertTrue($subProcessFinished->uuid()->equals($receivedMessage->uuid()));
     $this->assertTrue($logMessage->uuid()->equals($receivedMessage->lastMessage()->uuid()));
     $this->assertEquals($logMessage->technicalMsg(), $receivedMessage->lastMessage()->technicalMsg());
     $this->assertEquals($subProcessFinished->createdAt()->format('Y-m-d H:i:s'), $receivedMessage->createdAt()->format('Y-m-d H:i:s'));
 }
Ejemplo n.º 9
0
 /**
  * If workflow message handler receives a process-data message it forwards the message to this
  * method and uses the returned ProcessingMessage as response
  *
  * @param WorkflowMessage $workflowMessage
  * @return ProcessingMessage
  */
 protected function handleProcessData(WorkflowMessage $workflowMessage)
 {
     try {
         return $this->processData($workflowMessage);
     } catch (\Exception $ex) {
         ErrorHandler::stop();
         return LogMessage::logException($ex, $workflowMessage);
     }
 }
 /**
  * @param WorkflowMessage $message
  * @param bool $forceInsert
  * @return LogMessage|WorkflowMessage
  */
 private function updateOrInsertPayload(WorkflowMessage $message, $forceInsert = false)
 {
     $processingType = $message->payload()->getTypeClass();
     /** @var $desc Description */
     $desc = $processingType::buildDescription();
     $successful = 0;
     $failed = 0;
     $failedMessages = [];
     if ($desc->nativeType() == NativeType::COLLECTION) {
         /** @var $prototype Prototype */
         $prototype = $processingType::prototype();
         $itemProto = $prototype->typeProperties()['item']->typePrototype();
         $typeObj = $message->payload()->toType();
         if ($typeObj) {
             $this->connection->beginTransaction();
             $insertStmt = null;
             /** @var $tableRow TableRow */
             foreach ($typeObj as $i => $tableRow) {
                 if (!$tableRow instanceof TableRow) {
                     return LogMessage::logUnsupportedMessageReceived($message);
                 }
                 try {
                     $insertStmt = $this->updateOrInsertTableRow($tableRow, $forceInsert, $insertStmt);
                     $successful++;
                 } catch (\Exception $e) {
                     $datasetIndex = $tableRow->description()->hasIdentifier() ? $tableRow->description()->identifierName() . " = " . $tableRow->property($tableRow->description()->identifierName())->value() : $i;
                     $failed++;
                     $failedMessages[] = sprintf('Dataset %s: %s', $datasetIndex, $e->getMessage());
                 }
             }
             $this->connection->commit();
         }
         $report = [MessageMetadata::SUCCESSFUL_ITEMS => $successful, MessageMetadata::FAILED_ITEMS => $failed, MessageMetadata::FAILED_MESSAGES => $failedMessages];
         if ($failed > 0) {
             return LogMessage::logItemsProcessingFailed($successful, $failed, $failedMessages, $message);
         } else {
             return $message->answerWithDataProcessingCompleted($report);
         }
     } else {
         $tableRow = $message->payload()->toType();
         if (!$tableRow instanceof TableRow) {
             return LogMessage::logUnsupportedMessageReceived($message);
         }
         $this->updateOrInsertTableRow($tableRow, $forceInsert);
         return $message->answerWithDataProcessingCompleted();
     }
 }
Ejemplo n.º 11
0
 /**
  * @param TaskListPosition $taskListPosition
  * @param WorkflowMessage|LogMessage $lastAnswer
  * @throws \RuntimeException If process cannot be found
  * @throws \Exception If error occurs during processing
  */
 private function continueProcessAt(TaskListPosition $taskListPosition, $lastAnswer)
 {
     $process = $this->processRepository->get($taskListPosition->taskListId()->processId());
     if (is_null($process)) {
         throw new \RuntimeException(sprintf("Last received message %s (%s) contains unknown processId. A process with id %s cannot be found!", $lastAnswer->getMessageName(), $lastAnswer->uuid()->toString(), $taskListPosition->taskListId()->processId()->toString()));
     }
     $this->beginTransaction();
     try {
         $process->receiveMessage($lastAnswer, $this->workflowEngine);
         $this->commitTransaction();
     } catch (\Exception $ex) {
         $this->rollbackTransaction();
         throw $ex;
     }
     if ($process->isFinished()) {
         $this->processorEventQueue->enqueue($this->events()->getNewActionEvent('process_did_finish', $this, ['process_id' => $process->processId()->toString(), 'finished_at' => $lastAnswer->createdAt()->format(\DateTime::ISO8601), 'succeed' => $process->isSuccessfulDone()]));
     }
     if ($process->isSubProcess() && $process->isFinished()) {
         if ($process->isSuccessfulDone()) {
             $this->informParentProcessAboutSubProcess($process, true, $lastAnswer);
         } else {
             if (!$lastAnswer instanceof LogMessage) {
                 $lastAnswer = LogMessage::logException(new \RuntimeException("Sub process failed but last message was not a LogMessage"), $process->parentTaskListPosition());
             }
             if (!$lastAnswer->isError()) {
                 $lastAnswer = LogMessage::logErrorMsg($lastAnswer->technicalMsg(), $lastAnswer);
             }
             $this->informParentProcessAboutSubProcess($process, false, $lastAnswer);
         }
     }
 }
Ejemplo n.º 12
0
 protected function setLogFromArray(array $log)
 {
     foreach ($log as $sbMessageArr) {
         $sbMessage = RemoteMessage::fromArray($sbMessageArr);
         $this->log[] = LogMessage::fromServiceBusMessage($sbMessage);
     }
 }
Ejemplo n.º 13
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);
 }
 /**
  * @test
  */
 public function it_dispatches_a_sub_process_finished_event()
 {
     $taskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1);
     $wfMessage = $this->getUserDataCollectedTestMessage();
     $wfMessage->connectToProcessTask($taskListPosition);
     $logMessage = LogMessage::logDebugMsg("Just a fake event", $wfMessage);
     $subProcessFinished = SubProcessFinished::record(NodeName::defaultName(), $taskListPosition->taskListId()->processId(), true, $logMessage, $taskListPosition);
     $this->workflowEngine->dispatch($subProcessFinished);
     $this->assertSame($subProcessFinished, $this->receivedMessage);
 }
Ejemplo n.º 15
0
 /**
  * @param LogMessage $message
  * @return MessageLogEntry
  */
 public static function logLogMessage(LogMessage $message)
 {
     return self::createFromMessageProps($message->uuid(), $message->messageName(), 1, $message->processTaskListPosition());
 }
Ejemplo n.º 16
0
 /**
  * @param LogMessageReceived $event
  */
 protected function whenLogMessageReceived(LogMessageReceived $event)
 {
     $taskListEntry = $this->taskList->getTaskListEntryAtPosition($event->taskListPosition());
     $sbMessage = RemoteMessage::fromArray($event->payload()['message']);
     $taskListEntry->logMessage(LogMessage::fromServiceBusMessage($sbMessage));
 }
Ejemplo n.º 17
0
 /**
  * @test
  */
 public function it_is_capable_of_logging_messages()
 {
     $taskListEntry = $this->getTestTaskListEntry();
     $wfMessage = $this->getUserDataCollectedTestMessage();
     $wfMessage->connectToProcessTask($taskListEntry->taskListPosition());
     $info = LogMessage::logInfoDataProcessingStarted($wfMessage);
     $taskListEntry->logMessage($info);
     $warning = LogMessage::logWarningMsg("Just a warning", $wfMessage);
     $taskListEntry->logMessage($warning);
     $log = $taskListEntry->messageLog();
     $this->assertEquals(2, count($log));
     $this->assertSame($info, $log[0]);
     $this->assertSame($warning, $log[1]);
 }
Ejemplo n.º 18
0
 /**
  * @test
  */
 function it_can_log_a_items_processing_failed_message_with_a_failed_msg_for_each_failed_item()
 {
     $wfMessage = $this->getTestWorkflowMessage();
     $successfulItems = 3;
     $failedItems = 2;
     $failedMsgs = ['Processing failed!', 'Processing failed, too!'];
     $logMsg = LogMessage::logItemsProcessingFailed($successfulItems, $failedItems, $failedMsgs, $wfMessage);
     $this->assertTrue($logMsg->isError());
     $this->assertEquals(LogMessage::ERROR_ITEMS_PROCESSING_FAILED, $logMsg->msgCode());
     $this->assertEquals('Processing for 2 of 5 items failed', $logMsg->technicalMsg());
     $msgParams = $logMsg->msgParams();
     $this->assertTrue(isset($msgParams[LogMessage::MSG_PARAM_SUCCESSFUL_ITEMS]));
     $this->assertTrue(isset($msgParams[LogMessage::MSG_PARAM_FAILED_ITEMS]));
     $this->assertTrue(isset($msgParams[LogMessage::MSG_PARAM_FAILED_MESSAGES]));
     $this->assertEquals($successfulItems, $msgParams[LogMessage::MSG_PARAM_SUCCESSFUL_ITEMS]);
     $this->assertEquals($failedItems, $msgParams[LogMessage::MSG_PARAM_FAILED_ITEMS]);
     $this->assertEquals($failedMsgs, $msgParams[LogMessage::MSG_PARAM_FAILED_MESSAGES]);
 }
 /**
  * If workflow message handler receives a process-data message it forwards the message to this
  * method and uses the returned ProcessingMessage as response
  *
  * @param WorkflowMessage $workflowMessage
  * @return ProcessingMessage
  */
 protected function handleProcessData(WorkflowMessage $workflowMessage)
 {
     $this->lastProcessDataMessage = $workflowMessage;
     return LogMessage::logDebugMsg("Process data message received", $workflowMessage->processTaskListPosition());
 }
Ejemplo n.º 20
0
 /**
  * @test
  */
 public function it_marks_task_of_parent_process_as_failed_when_sub_process_is_finished_with_error()
 {
     $this->setUpOtherMachine();
     $wfMessage = $this->getUserDataCollectedTestMessage();
     /**
      * Change type to scenario 2 type, so that @see \Prooph\ProcessingTest\TestCase::getTestProcessFactory
      * set up the right process
      */
     $wfMessage->changeProcessingType('Prooph\\ProcessingTest\\Mock\\UserDictionaryS2');
     $this->getTestWorkflowProcessor()->receiveMessage($wfMessage);
     $receivedMessage = $this->otherMachineWorkflowMessageHandler->lastWorkflowMessage();
     $this->assertNotNull($receivedMessage);
     $error = LogMessage::logErrorMsg("Simulated error", $receivedMessage);
     $this->getOtherMachineWorkflowProcessor()->receiveMessage($error);
     $this->assertNotNull($this->lastPostCommitEvent);
     $expectedEventNamesLocalhost = ['Prooph\\Processing\\Processor\\Event\\ProcessWasSetUp', 'Prooph\\Processing\\Processor\\Task\\Event\\TaskEntryMarkedAsRunning', 'Prooph\\Processing\\Processor\\Task\\Event\\LogMessageReceived', 'Prooph\\Processing\\Processor\\Task\\Event\\TaskEntryMarkedAsFailed'];
     $expectedEventNamesOtherMachine = ['Prooph\\Processing\\Processor\\Event\\ProcessWasSetUp', 'Prooph\\Processing\\Processor\\Task\\Event\\TaskEntryMarkedAsRunning', 'Prooph\\Processing\\Processor\\Task\\Event\\LogMessageReceived', 'Prooph\\Processing\\Processor\\Task\\Event\\TaskEntryMarkedAsFailed'];
     $this->assertEquals($expectedEventNamesLocalhost, $this->eventNameLog);
     $this->assertEquals($expectedEventNamesOtherMachine, $this->otherMachineEventNameLog);
 }
Ejemplo n.º 21
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);
 }
Ejemplo n.º 22
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()));
 }
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
 public static function record(LogMessage $logMessage)
 {
     return self::at($logMessage->processTaskListPosition(), array('message' => $logMessage->toServiceBusMessage()->toArray()));
 }