/** * @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()); }
/** * @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()); } }
/** * Transforms current message to a process data command * * @param \Prooph\Processing\Processor\Task\TaskListPosition $newTaskListPosition * @param string|NodeName $target * @param array $metadata * @return WorkflowMessage */ public function prepareDataProcessing(TaskListPosition $newTaskListPosition, $target, array $metadata = []) { $type = MessageNameUtils::getTypePartOfMessageName($this->messageName); $metadata = ArrayUtils::merge($this->metadata, $metadata); return new self($this->payload, MessageNameUtils::getProcessDataCommandName($type), $this->target, $target, $metadata, $newTaskListPosition, $this->version + 1); }
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]); }
/** * @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()); }
/** * 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; }
/** * @test */ public function it_returns_a_process_data_command_name_including_the_type_class_normalized() { $commandName = MessageNameUtils::getProcessDataCommandName('Prooph\\ProcessingTest\\Mock\\UserDictionary'); $this->assertEquals(MessageNameUtils::MESSAGE_NAME_PREFIX . 'proophprocessingtestmockuserdictionary-process-data', $commandName); }