/** * @test */ public function it_injects_target_handler_to_event_dispatch_when_event_is_a_workflow_message() { $message = WorkflowMessage::newDataCollected(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]), 'test-case', NodeName::defaultName()); $eventDispatch = new EventDispatch(); $eventDispatch->setEvent($message); $router = new SingleTargetMessageRouter($this->getTestWorkflowProcessor()); $router->onRouteEvent($eventDispatch); $this->assertSame($this->getTestWorkflowProcessor(), $eventDispatch->getEventListeners()[0]); }
/** * @test */ public function it_handles_a_process_data_message() { $taskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 2); $wfMessage = WorkflowMessage::newDataCollected(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]), 'test-case', NodeName::defaultName()); $wfMessage->connectToProcessTask($taskListPosition); $wfMessage = $wfMessage->prepareDataProcessing($taskListPosition, 'message-handler'); $this->workflowMessageHandler->handleWorkflowMessage($wfMessage); $this->assertSame($wfMessage, $this->workflowMessageHandler->lastProcessDataMessage()); $this->assertInstanceOf('Prooph\\Processing\\Message\\LogMessage', $this->lastProcessingMessage); }
/** * @test */ public function it_returns_start_sub_process_command_including_previous_message() { $subProcessDefinition = ["process_type" => Definition::PROCESS_LINEAR_MESSAGING, "tasks" => [["task_type" => Definition::TASK_COLLECT_DATA, "source" => 'test-case', "processing_type" => 'Prooph\\ProcessingTest\\Mock\\UserDictionary']]]; $task = RunSubProcess::setUp(NodeName::defaultName(), $subProcessDefinition); $parentTaskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1); $previousMessage = WorkflowMessage::newDataCollected(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]), 'test-case', NodeName::defaultName()); $startSubProcess = $task->generateStartCommandForSubProcess($parentTaskListPosition, $previousMessage); $this->assertTrue($parentTaskListPosition->equals($startSubProcess->parentTaskListPosition())); $this->assertEquals($subProcessDefinition, $startSubProcess->subProcessDefinition()); $this->assertEquals($previousMessage->messageName(), $startSubProcess->previousWorkflowMessage()->messageName()); }
/** * @test */ public function it_creates_an_event_bus_that_dispatches_a_message_to_a_workflow_processor() { $env = Environment::setUp(); $processor = new StupidWorkflowProcessorMock(); $env->services()->set(Definition::SERVICE_WORKFLOW_PROCESSOR, $processor, true); $eventBus = $env->services()->get('processing.event_bus.' . Definition::SERVICE_WORKFLOW_PROCESSOR); $this->assertInstanceOf('Prooph\\ServiceBus\\EventBus', $eventBus); $message = WorkflowMessage::newDataCollected(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]), 'test-case', NodeName::defaultName()); $eventBus->dispatch($message); $this->assertSame($message, $processor->getLastReceivedMessage()); }
/** * @test */ public function it_collects_information_for_the_sub_process() { $subProcessDefinition = ["process_type" => Definition::PROCESS_LINEAR_MESSAGING, "tasks" => [["task_type" => Definition::TASK_COLLECT_DATA, "source" => 'test-case', "processing_type" => 'Prooph\\ProcessingTest\\Mock\\UserDictionary']]]; $previousMessage = WorkflowMessage::newDataCollected(UserDictionary::fromNativeValue(['id' => 1, 'name' => 'John Doe', 'address' => ['street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City']]), 'test-case', 'processor'); $parentTaskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1); $command = StartSubProcess::at($parentTaskListPosition, $subProcessDefinition, true, 'sub-processor', $previousMessage); $this->assertTrue($parentTaskListPosition->equals($command->parentTaskListPosition())); $this->assertTrue($command->syncLogMessages()); $this->assertEquals($subProcessDefinition, $command->subProcessDefinition()); $this->assertEquals($previousMessage->messageName(), $command->previousWorkflowMessage()->messageName()); $this->assertEquals(NodeName::defaultName()->toString(), $command->origin()); $this->assertEquals('sub-processor', $command->target()); }
/** * @test */ public function it_invokes_processing_event_on_workflow_message_handler() { $userData = array('id' => 1, 'name' => 'Alex', 'address' => array('street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City')); $user = UserDictionary::fromNativeValue($userData); $wfEvent = WorkflowMessage::newDataCollected($user, 'test-case', NodeName::defaultName()); $eventBus = new EventBus(); $eventRouter = new EventRouter(); $eventRouter->route($wfEvent->messageName())->to($this->workflowMessageHandler); $eventBus->utilize($eventRouter); $eventBus->utilize(new HandleWorkflowMessageInvokeStrategy()); $eventBus->dispatch($wfEvent); $this->assertSame($wfEvent, $this->workflowMessageHandler->lastWorkflowMessage()); }
/** * @test * @dataProvider provideStringCollection */ public function it_performs_a_sub_process_for_each_chunk_of_a_collection(StringCollection $stringCollection) { $processDefinition = ['process_type' => Definition::PROCESS_PARALLEL_CHUNK, 'tasks' => [["task_type" => Definition::TASK_RUN_SUB_PROCESS, "target_node_name" => NodeName::defaultName()->toString(), "process_definition" => ["process_type" => Definition::PROCESS_LINEAR_MESSAGING, "tasks" => [["task_type" => Definition::TASK_PROCESS_DATA, "target" => 'test-target', "allowed_types" => ['Prooph\\Processing\\Type\\String']]]]]]]; $processFactory = new ProcessFactory(); $chunkProcess = $processFactory->createProcessFromDefinition($processDefinition, NodeName::defaultName()); $this->assertInstanceOf('Prooph\\Processing\\Processor\\ChunkProcess', $chunkProcess); $message = WorkflowMessage::newDataCollected($stringCollection, 'test-case', NodeName::defaultName(), [ChunkProcess::META_OFFSET => 0, ChunkProcess::META_LIMIT => 2, ChunkProcess::META_TOTAL_ITEMS => 6, ChunkProcess::META_COUNT_ONLY => true]); $chunkProcess->perform($this->workflowEngine, $message); $this->assertEquals(3, count($this->startSubProcessCommands)); $this->assertFalse($chunkProcess->isFinished()); foreach ($this->startSubProcessCommands as $i => $command) { $mockedMessage = WorkflowMessage::newDataCollected(String::fromNativeValue("Fake message"), 'test-case', NodeName::defaultName()); $mockedMessage->connectToProcessTask($command->parentTaskListPosition()); $chunkProcess->receiveMessage($mockedMessage, $this->workflowEngine); } $this->assertTrue($chunkProcess->isSuccessfulDone()); }
/** * @test */ function it_does_not_perform_the_delete_query_when_no_listener_adds_a_condition() { $taskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1); $metadata = [DoctrineTableGateway::META_TRY_UPDATE => true]; $users = TestUserCollection::fromNativeValue([['id' => null, 'name' => 'John Doe', 'age' => 29], ['id' => null, 'name' => 'Maxi Mustermann', 'age' => 41]]); $message = WorkflowMessage::newDataCollected($users, 'test-case', 'localhost'); $message->connectToProcessTask($taskListPosition); $message = $message->prepareDataProcessing($taskListPosition, 'localhost', $metadata); $this->tableGateway->handleWorkflowMessage($message); $this->assertInstanceOf('Prooph\\Processing\\Message\\WorkflowMessage', $this->messageReceiver->getLastReceivedMessage()); /** @var $message WorkflowMessage */ $message = $this->messageReceiver->getLastReceivedMessage(); $metadata = $message->metadata(); $this->assertTrue(isset($metadata[MessageMetadata::SUCCESSFUL_ITEMS])); $this->assertEquals(2, $metadata[MessageMetadata::SUCCESSFUL_ITEMS]); $this->assertTrue(isset($metadata[MessageMetadata::FAILED_ITEMS])); $this->assertEquals(0, $metadata[MessageMetadata::FAILED_ITEMS]); $this->assertTrue(isset($metadata[MessageMetadata::FAILED_MESSAGES])); $this->assertEmpty($metadata[MessageMetadata::FAILED_MESSAGES]); $query = $this->getDbalConnection()->createQueryBuilder(); $userResultSet = $query->select('*')->from(self::TEST_TABLE)->execute()->fetchAll(); $this->assertEquals(5, count($userResultSet)); $expectedUsers = [['id' => '1', 'name' => 'John Doe', 'age' => '34'], ['id' => '2', 'name' => 'Max Mustermann', 'age' => '41'], ['id' => '3', 'name' => 'Donald Duck', 'age' => '57'], ['id' => '4', 'name' => 'John Doe', 'age' => '29'], ['id' => '5', 'name' => 'Maxi Mustermann', 'age' => '41']]; $this->assertEquals($expectedUsers, $userResultSet); }
/** * @return WorkflowMessage */ protected function getUserDataCollectedTestMessage() { $userData = array('id' => 1, 'name' => 'Alex', 'address' => array('street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City')); $user = UserDictionary::fromNativeValue($userData); return WorkflowMessage::newDataCollected($user, 'test-case', NodeName::defaultName()->toString()); }
/** * @test */ function it_creates_linear_messaging_process_with_manipulate_payload_task_from_definition() { $definition = ["process_type" => Definition::PROCESS_LINEAR_MESSAGING, "tasks" => [["task_type" => Definition::TASK_MANIPULATE_PAYLOAD, 'manipulation_script' => __DIR__ . '/../Mock/manipulation/append_world.php']]]; $processFactory = new ProcessFactory(); $process = $processFactory->createProcessFromDefinition($definition, NodeName::defaultName()); $this->assertInstanceOf('Prooph\\Processing\\Processor\\LinearProcess', $process); $message = WorkflowMessage::newDataCollected(String::fromString('Hello'), 'test-case', NodeName::defaultName()); $process->perform($this->workflowEngine, $message); $this->assertTrue($process->isSuccessfulDone()); $this->assertEquals('Hello World', $message->payload()->extractTypeData()); }
$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; } //Let's start the example $workflowProcessor = set_up_workflow_environment(); //Step 1: Read source data $userData = (include 'data/user-source-data.php'); //Step 2: Use implementation of Prooph\Processing\Type\Type to validate source data $user = \Prooph\ProcessingExample\Type\SourceUser::fromNativeValue($userData); //Step 3: Prepare WorkflowMessage $userDataCollected = \Prooph\Processing\Message\WorkflowMessage::newDataCollected($user, 'example-script', \Prooph\Processing\Processor\NodeName::defaultName()); //Step 4: Start processing by sending a "data-collected" event to the WorkflowProcessor (simplified step without using an EventBus) $workflowProcessor->receiveMessage($userDataCollected); //Done: Check examples/data/target-data.txt. You should see the json representation of user data. If not please check //output of your console window. The script prints the log of the process on the screen
/** * @param CollectionType $collection * @param WorkflowEngine $workflowEngine */ private function startSubProcessForEachItem(CollectionType $collection, WorkflowEngine $workflowEngine) { $taskListEntry = $this->taskList->getNextNotStartedTaskListEntry(); $this->recordThat(TaskEntryMarkedAsRunning::at($taskListEntry->taskListPosition())); $this->processingCollection = true; /** @var $task RunSubProcess */ $task = $taskListEntry->task(); foreach ($collection as $item) { $message = WorkflowMessage::newDataCollected($item, $this->taskList->taskListId()->nodeName(), $task->targetNodeName()); $message->connectToProcessTask($taskListEntry->taskListPosition()); $this->recordThat(MultiPerformTaskWasStarted::at($taskListEntry->taskListPosition())); $this->performRunSubProcess($task, $taskListEntry->taskListPosition(), $workflowEngine, $message); } $this->processingCollection = false; }
/** * @test */ public function it_writes_each_string_of_the_collection_to_a_separate_file_and_the_value_is_available_in_the_filename_template_to_create_unique_file_names() { $taskListPosition = TaskListPosition::at(TaskListId::linkWith(NodeName::defaultName(), ProcessId::generate()), 1); $strings = StringCollection::fromNativeValue(["first", "second", "third"]); $metadata = [FileGateway::META_FILE_TYPE => 'json', FileGateway::META_PATH => $this->tempPath, FileGateway::META_FILENAME_TEMPLATE => 'string-{{value}}.json', FileGateway::META_WRITE_MULTI_FILES => true]; $this->tempFiles[] = 'string-first.json'; $this->tempFiles[] = 'string-second.json'; $this->tempFiles[] = 'string-third.json'; $workflowMessage = WorkflowMessage::newDataCollected($strings, NodeName::defaultName()->toString(), 'file-connector'); $workflowMessage->connectToProcessTask($taskListPosition); $workflowMessage = $workflowMessage->prepareDataProcessing($taskListPosition, NodeName::defaultName()->toString(), $metadata); $this->fileGateway->handleWorkflowMessage($workflowMessage); $this->assertInstanceOf('Prooph\\Processing\\Message\\WorkflowMessage', $this->messageReceiver->getLastReceivedMessage()); $this->assertTrue(file_exists($this->tempPath . $this->tempFiles[0])); $this->assertTrue(file_exists($this->tempPath . $this->tempFiles[1])); $this->assertTrue(file_exists($this->tempPath . $this->tempFiles[2])); $second = json_decode(file_get_contents($this->tempPath . $this->tempFiles[1])); $this->assertEquals('second', $second); }
/** * @test */ public function it_dispatches_a_workflow_message_event() { $userData = array('id' => 1, 'name' => 'Alex', 'address' => array('street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City')); $user = UserDictionary::fromNativeValue($userData); $wfMessage = WorkflowMessage::newDataCollected($user, 'test-case', NodeName::defaultName(), []); $this->workflowEngine->dispatch($wfMessage); $this->assertSame($wfMessage, $this->receivedMessage); }
/** * @test */ public function it_changes_processing_type_in_message_name_and_payload() { $userData = array('id' => 1, 'name' => 'Alex', 'address' => array('street' => 'Main Street', 'streetNumber' => 10, 'zip' => '12345', 'city' => 'Test City')); $user = UserDictionary::fromNativeValue($userData); $wfMessage = WorkflowMessage::newDataCollected($user, 'test-case', NodeName::defaultName()->toString()); $wfMessage->changeProcessingType('Prooph\\ProcessingTest\\Mock\\TargetUserDictionary'); $this->assertEquals(MessageNameUtils::MESSAGE_NAME_PREFIX . 'proophprocessingtestmocktargetuserdictionary-data-collected', $wfMessage->messageName()); $this->assertEquals('Prooph\\ProcessingTest\\Mock\\TargetUserDictionary', $wfMessage->payload()->getTypeClass()); }