├── .gitignore
├── .scrutinizer.yml
├── Api
├── ChunkSizeCalculatorInterface.php
├── CustomerIdsProviderInterface.php
├── Data
│ ├── HtmlInterface.php
│ ├── ProcessInterface.php
│ └── UrlInterface.php
├── Report
│ ├── CliReportManagerInterface.php
│ ├── ReportGeneratorInterface.php
│ ├── ReportSenderInterface.php
│ └── WebapiReportManagerInterface.php
└── TimerInterface.php
├── Console
└── Command
│ ├── GenerateReports.php
│ ├── StartCliReportingService.php
│ └── StartWebapiReportingService.php
├── Exception
└── TimerException.php
├── LICENSE
├── Model
├── Adapter
│ └── ReactPHP
│ │ ├── ClientFactory.php
│ │ └── ProcessFactory.php
├── ChunkSizeCalculator.php
├── Data
│ ├── Html.php
│ ├── Process.php
│ └── Url.php
├── FakeCustomerIdsProvider.php
├── Report
│ ├── CliReportManager.php
│ ├── ReportGenerator.php
│ ├── ReportSender.php
│ └── WebapiReportManager.php
└── Timer.php
├── README.md
├── Standalone
├── ChildProcess
│ ├── AsynchronousProcessRunner.php
│ ├── HalfAsynchronousProcessRunner.php
│ ├── ProcessRunnerInterface.php
│ ├── SynchronousProcessRunner.php
│ └── processes
│ │ ├── pi
│ │ ├── primes
│ │ ├── random
│ │ └── sleep
├── Http
│ ├── AsynchronousClient.php
│ ├── ClientInterface.php
│ ├── HalfAsynchronousClient.php
│ ├── SynchronousClient.php
│ └── UrlProvider.php
└── bin
│ ├── childprocess
│ └── http
├── Test
└── Unit
│ ├── Console
│ └── Command
│ │ ├── GenerateReportsTest.php
│ │ ├── StartCliReportingServiceTest.php
│ │ └── StartWebapiReportingServiceTest.php
│ ├── Model
│ ├── Adapter
│ │ └── ReactPHP
│ │ │ ├── ClientFactoryTest.php
│ │ │ └── ProcessFactoryTest.php
│ ├── ChunkSizeCalculatorTest.php
│ ├── Data
│ │ ├── HtmlTest.php
│ │ ├── ProcessTest.php
│ │ └── UrlTest.php
│ ├── FakeCustomerIdsProviderTest.php
│ ├── Report
│ │ ├── CliReportManagerTest.php
│ │ └── WebapiReportManagerTest.php
│ └── TimerTest.php
│ └── Standalone
│ ├── ChildProcess
│ ├── AsynchronousProcessRunnerTest.php
│ ├── HalfAsynchronousProcessRunnerTest.php
│ └── SynchronousProcessRunnerTest.php
│ └── Http
│ ├── AsynchronousClientTest.php
│ ├── HalfAsynchronousClientTest.php
│ ├── SynchronousClientTest.php
│ └── UrlProviderTest.php
├── composer.json
├── composer.lock
├── docs
├── magento_cli_1.png
├── magento_cli_3.png
└── standalone_cli.png
├── etc
├── di.xml
├── module.xml
└── webapi.xml
└── registration.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | .idea
3 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | checks:
2 | php:
3 | code_rating: true
4 | duplication: true
5 | excluded_dependencies:
6 | - magento/framework
7 | - magento/module-catalog-inventory
8 | - magento/module-cron
9 | - magento/module-integration
10 | - magento/module-rss
11 | - magento/module-theme
12 | - magento/module-customer
13 | - magento/module-gift-message
14 | - magento/module-page-cache
15 | - magento/module-sales-sequence
16 | - magento/module-user
17 | - magento/module-authorization
18 | - magento/module-developer
19 | - magento/module-grouped-product
20 | - magento/module-quote
21 | - magento/module-security
22 | - magento/module-wishlist
23 | - magento/module-catalog-import-export
24 | - magento/module-directory
25 | - magento/module-indexer
26 | - magento/module-require-js
27 | - magento/module-shipping
28 | - magento/module-cms
29 | - magento/module-backend
30 | - magento/module-catalog
31 | - magento/module-media-storage
32 | - magento/module-store
33 | - magento/module-backup
34 | - magento/module-cms-url-rewrite
35 | - magento/module-reports
36 | - magento/module-translation
37 | - magento/module-bundle
38 | - magento/module-downloadable
39 | - magento/module-sales
40 | - magento/module-ui
41 | - magento/module-checkout
42 | - magento/module-product-alert
43 | - magento/module-variable
44 | - magento/module-eav
45 | - magento/module-contact
46 | - magento/module-newsletter
47 | - magento/module-sales-rule
48 | - magento/module-deploy
49 | - magento/module-payment
50 | - magento/module-url-rewrite
51 |
52 | filter:
53 | excluded_paths:
54 | - "Test/"
55 |
56 | build:
57 | dependencies:
58 | before:
59 | - 'echo "{\"http-basic\":{\"repo.magento.com\":{\"username\":\"${MAGENTO_USERNAME}\",\"password\":\"${MAGENTO_PASSWORD}\"}}}" > auth.json'
--------------------------------------------------------------------------------
/Api/ChunkSizeCalculatorInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api;
12 |
13 | /**
14 | * Interface ChunkSizeCalculatorInterface
15 | * @package MSlwk\ReactPhpPlayground\Api
16 | */
17 | interface ChunkSizeCalculatorInterface
18 | {
19 | /**
20 | * @param array $elements
21 | * @param int $numberOfParts
22 | * @return int
23 | */
24 | public function calculateChunkSize(array $elements, int $numberOfParts): int;
25 | }
26 |
--------------------------------------------------------------------------------
/Api/CustomerIdsProviderInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api;
12 |
13 | /**
14 | * Interface CustomerIdsProviderInterface
15 | * @package MSlwk\ReactPhpPlayground\Api
16 | */
17 | interface CustomerIdsProviderInterface
18 | {
19 | /**
20 | * @return int[]
21 | */
22 | public function getCustomerIds(): array;
23 | }
24 |
--------------------------------------------------------------------------------
/Api/Data/HtmlInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Data;
12 |
13 | /**
14 | * Interface HtmlInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Data
16 | */
17 | interface HtmlInterface
18 | {
19 | /**
20 | * @return string
21 | */
22 | public function getHtml(): string;
23 | }
24 |
--------------------------------------------------------------------------------
/Api/Data/ProcessInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Data;
12 |
13 | /**
14 | * Interface ProcessInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Data
16 | */
17 | interface ProcessInterface
18 | {
19 | /**
20 | * @return string
21 | */
22 | public function getCommand(): string;
23 | }
24 |
--------------------------------------------------------------------------------
/Api/Data/UrlInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Data;
12 |
13 | /**
14 | * Interface UrlInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Data
16 | */
17 | interface UrlInterface
18 | {
19 | /**
20 | * @return string
21 | */
22 | public function getUrl(): string;
23 | }
24 |
--------------------------------------------------------------------------------
/Api/Report/CliReportManagerInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Report;
12 |
13 | /**
14 | * Interface CliReportManagerInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Report
16 | */
17 | interface CliReportManagerInterface
18 | {
19 | /**
20 | * @param int[] $customerIds
21 | * @return void
22 | */
23 | public function generateAndSendReportForCustomers(array $customerIds): void;
24 | }
25 |
--------------------------------------------------------------------------------
/Api/Report/ReportGeneratorInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Report;
12 |
13 | /**
14 | * Interface ReportGeneratorInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Report
16 | */
17 | interface ReportGeneratorInterface
18 | {
19 | /**
20 | * @param int $customerId
21 | * @return string
22 | */
23 | public function generateReport(int $customerId): string;
24 | }
25 |
--------------------------------------------------------------------------------
/Api/Report/ReportSenderInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Report;
12 |
13 | /**
14 | * Interface ReportSenderInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Report
16 | */
17 | interface ReportSenderInterface
18 | {
19 | /**
20 | * @param string $report
21 | * @return void
22 | */
23 | public function sendReport(string $report): void;
24 | }
25 |
--------------------------------------------------------------------------------
/Api/Report/WebapiReportManagerInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api\Report;
12 |
13 | /**
14 | * Interface WebapiReportManagerInterface
15 | * @package MSlwk\ReactPhpPlayground\Api\Report
16 | */
17 | interface WebapiReportManagerInterface
18 | {
19 | /**
20 | * @param int[] $customerIds
21 | * @return string[]
22 | */
23 | public function generateAndSendReportForCustomers(array $customerIds): array;
24 | }
25 |
--------------------------------------------------------------------------------
/Api/TimerInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Api;
12 |
13 | use MSlwk\ReactPhpPlayground\Exception\TimerException;
14 |
15 | /**
16 | * Interface TimerInterface
17 | * @package MSlwk\ReactPhpPlayground\Api
18 | */
19 | interface TimerInterface
20 | {
21 | /**
22 | * @return void
23 | */
24 | public function startTimer(): void;
25 |
26 | /**
27 | * @return void
28 | * @throws TimerException
29 | */
30 | public function stopTimer(): void;
31 |
32 | /**
33 | * @return float
34 | * @throws TimerException
35 | */
36 | public function getExecutionTimeInSeconds(): float;
37 | }
38 |
--------------------------------------------------------------------------------
/Console/Command/GenerateReports.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Console\Command;
12 |
13 | use Magento\Framework\Serialize\Serializer\Json;
14 | use MSlwk\ReactPhpPlayground\Api\Report\CliReportManagerInterface;
15 | use Symfony\Component\Console\Command\Command;
16 | use Symfony\Component\Console\Input\InputArgument;
17 | use Symfony\Component\Console\Input\InputInterface;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 |
20 | /**
21 | * Class GenerateReports
22 | * @package MSlwk\ReactPhpPlayground\Console\Command
23 | */
24 | class GenerateReports extends Command
25 | {
26 | const COMMAND_NAME = 'mslwk:generate-reports';
27 | const COMMAND_DESCRIPTION = 'Generate reports for customers with IDs supplied';
28 | const ARGUMENT_CUSTOMER_IDS = 'customer-ids';
29 |
30 | /**
31 | * @var Json
32 | */
33 | private $jsonHandler;
34 |
35 | /**
36 | * @var CliReportManagerInterface
37 | */
38 | private $reportManager;
39 |
40 | /**
41 | * GenerateReports constructor.
42 | * @param Json $jsonHandler
43 | * @param CliReportManagerInterface $reportManager
44 | * @param null $name
45 | */
46 | public function __construct(
47 | Json $jsonHandler,
48 | CliReportManagerInterface $reportManager,
49 | $name = null
50 | ) {
51 | parent::__construct($name);
52 | $this->jsonHandler = $jsonHandler;
53 | $this->reportManager = $reportManager;
54 | }
55 |
56 | /**
57 | * {@inheritdoc}
58 | */
59 | protected function configure()
60 | {
61 | $this->setName(self::COMMAND_NAME)
62 | ->setDescription(self::COMMAND_DESCRIPTION)
63 | ->addArgument(
64 | self::ARGUMENT_CUSTOMER_IDS,
65 | InputArgument::REQUIRED
66 | );
67 | }
68 |
69 | /**
70 | * @param InputInterface $input
71 | * @param OutputInterface $output
72 | * @return void
73 | */
74 | protected function execute(InputInterface $input, OutputInterface $output)
75 | {
76 | $customerIds = $this->jsonHandler->unserialize($input->getArgument(self::ARGUMENT_CUSTOMER_IDS));
77 | $this->reportManager->generateAndSendReportForCustomers($customerIds);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Console/Command/StartCliReportingService.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Console\Command;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\ChunkSizeCalculatorInterface;
14 | use MSlwk\ReactPhpPlayground\Api\CustomerIdsProviderInterface;
15 | use MSlwk\ReactPhpPlayground\Api\TimerInterface;
16 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
17 | use Symfony\Component\Console\Command\Command;
18 | use Symfony\Component\Console\Input\InputArgument;
19 | use Symfony\Component\Console\Input\InputInterface;
20 | use Symfony\Component\Console\Output\OutputInterface;
21 | use Magento\Framework\Serialize\Serializer\Json;
22 | use React\EventLoop\Factory;
23 |
24 | /**
25 | * Class StartCliReportingService
26 | * @package MSlwk\ReactPhpPlayground\Console\Command
27 | */
28 | class StartCliReportingService extends Command
29 | {
30 | const COMMAND_NAME = 'mslwk:cli-reporting-start';
31 | const COMMAND_DESCRIPTION = 'Start asynchronous CLI reporting service';
32 | const ARGUMENT_NUMBER_OF_THREADS = 'threads';
33 |
34 | /**
35 | * @var TimerInterface
36 | */
37 | private $timer;
38 |
39 | /**
40 | * @var CustomerIdsProviderInterface
41 | */
42 | private $customerIdsProvider;
43 |
44 | /**
45 | * @var LoopInterface
46 | */
47 | private $loop;
48 |
49 | /**
50 | * @var ProcessFactory
51 | */
52 | private $processFactory;
53 |
54 | /**
55 | * @var Json
56 | */
57 | private $jsonHandler;
58 |
59 | /**
60 | * @var ChunkSizeCalculatorInterface
61 | */
62 | private $chunkSizeCalculator;
63 |
64 | /**
65 | * StartCliReportingService constructor.
66 | * @param TimerInterface $timer
67 | * @param CustomerIdsProviderInterface $customerIdsProvider
68 | * @param Factory $loopFactory
69 | * @param ProcessFactory $processFactory
70 | * @param Json $jsonHandler
71 | * @param ChunkSizeCalculatorInterface $chunkSizeCalculator
72 | * @param null $name
73 | */
74 | public function __construct(
75 | TimerInterface $timer,
76 | CustomerIdsProviderInterface $customerIdsProvider,
77 | Factory $loopFactory,
78 | ProcessFactory $processFactory,
79 | Json $jsonHandler,
80 | ChunkSizeCalculatorInterface $chunkSizeCalculator,
81 | $name = null
82 | ) {
83 | parent::__construct($name);
84 | $this->timer = $timer;
85 | $this->customerIdsProvider = $customerIdsProvider;
86 | $this->loop = $loopFactory::create();
87 | $this->processFactory = $processFactory;
88 | $this->jsonHandler = $jsonHandler;
89 | $this->chunkSizeCalculator = $chunkSizeCalculator;
90 | }
91 |
92 | /**
93 | * {@inheritdoc}
94 | */
95 | protected function configure()
96 | {
97 | $this->setName(self::COMMAND_NAME)
98 | ->setDescription(self::COMMAND_DESCRIPTION)
99 | ->addArgument(
100 | self::ARGUMENT_NUMBER_OF_THREADS,
101 | InputArgument::REQUIRED,
102 | 'Number of threads for running the export process'
103 | );
104 | }
105 |
106 | /**
107 | * @param InputInterface $input
108 | * @param OutputInterface $output
109 | * @return void
110 | */
111 | protected function execute(InputInterface $input, OutputInterface $output)
112 | {
113 | $numberOfThreads = (int)$input->getArgument(self::ARGUMENT_NUMBER_OF_THREADS);
114 | $customerIds = $this->customerIdsProvider->getCustomerIds();
115 |
116 | $this->timer->startTimer();
117 |
118 | $this->startProcesses($customerIds, $numberOfThreads);
119 |
120 | $this->timer->stopTimer();
121 |
122 | $output->writeln("Process finished after {$this->timer->getExecutionTimeInSeconds()} seconds");
123 | }
124 |
125 | /**
126 | * @param int[] $customerIds
127 | * @param int $numberOfThreads
128 | */
129 | protected function startProcesses(array $customerIds, int $numberOfThreads): void
130 | {
131 | $chunkSize = $this->chunkSizeCalculator->calculateChunkSize($customerIds, $numberOfThreads);
132 | $threadedCustomerIds = array_chunk($customerIds, $chunkSize);
133 | foreach ($threadedCustomerIds as $customerIdsForSingleThread) {
134 | $this->createProcessDefinition($this->getFullCommand($customerIdsForSingleThread));
135 | }
136 | $this->loop->run();
137 | }
138 |
139 | /**
140 | * @param string $command
141 | */
142 | protected function createProcessDefinition(string $command): void
143 | {
144 | $reactProcess = $this->processFactory->create($command);
145 | $reactProcess->start($this->loop);
146 |
147 | $reactProcess->stdout->on('data', function ($chunk) {
148 | echo $chunk;
149 | });
150 | }
151 |
152 | /**
153 | * @param int[] $customerIds
154 | * @return string
155 | */
156 | protected function getFullCommand(array $customerIds): string
157 | {
158 | return sprintf(
159 | ' %s/bin/magento %s %s',
160 | BP,
161 | GenerateReports::COMMAND_NAME,
162 | $this->jsonHandler->serialize($customerIds)
163 | );
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/Console/Command/StartWebapiReportingService.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Console\Command;
12 |
13 | use Magento\Framework\Serialize\Serializer\Json;
14 | use Magento\Store\Model\StoreManagerInterface;
15 | use MSlwk\ReactPhpPlayground\Api\ChunkSizeCalculatorInterface;
16 | use MSlwk\ReactPhpPlayground\Api\CustomerIdsProviderInterface;
17 | use MSlwk\ReactPhpPlayground\Api\TimerInterface;
18 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
19 | use React\EventLoop\Factory;
20 | use React\EventLoop\LoopInterface;
21 | use Symfony\Component\Console\Command\Command;
22 | use Symfony\Component\Console\Input\InputArgument;
23 | use Symfony\Component\Console\Input\InputInterface;
24 | use Symfony\Component\Console\Output\OutputInterface;
25 | use React\HttpClient\Response;
26 |
27 | /**
28 | * Class StartWebapiReportingService
29 | * @package MSlwk\ReactPhpPlayground\Console\Command
30 | */
31 | class StartWebapiReportingService extends Command
32 | {
33 | const COMMAND_NAME = 'mslwk:webapi-reporting-start';
34 | const COMMAND_DESCRIPTION = 'Start asynchronous WebAPI reporting service';
35 | const ARGUMENT_NUMBER_OF_THREADS = 'threads';
36 |
37 | const API_ENDPOINT_PATH = 'rest/V1/mslwk/customer-report/generate';
38 |
39 | /**
40 | * @var TimerInterface
41 | */
42 | private $timer;
43 |
44 | /**
45 | * @var CustomerIdsProviderInterface
46 | */
47 | private $customerIdsProvider;
48 |
49 | /**
50 | * @var LoopInterface
51 | */
52 | private $loop;
53 |
54 | /**
55 | * @var ClientFactory
56 | */
57 | private $clientFactory;
58 |
59 | /**
60 | * @var Json
61 | */
62 | private $jsonHandler;
63 |
64 | /**
65 | * @var StoreManagerInterface
66 | */
67 | private $storeManager;
68 |
69 | /**
70 | * @var ChunkSizeCalculatorInterface
71 | */
72 | private $chunkSizeCalculator;
73 |
74 | /**
75 | * StartWebapiReportingService constructor.
76 | * @param TimerInterface $timer
77 | * @param CustomerIdsProviderInterface $customerIdsProvider
78 | * @param Factory $loopFactory
79 | * @param ClientFactory $clientFactory
80 | * @param Json $jsonHandler
81 | * @param StoreManagerInterface $storeManager
82 | * @param ChunkSizeCalculatorInterface $chunkSizeCalculator
83 | * @param null $name
84 | */
85 | public function __construct(
86 | TimerInterface $timer,
87 | CustomerIdsProviderInterface $customerIdsProvider,
88 | Factory $loopFactory,
89 | ClientFactory $clientFactory,
90 | Json $jsonHandler,
91 | StoreManagerInterface $storeManager,
92 | ChunkSizeCalculatorInterface $chunkSizeCalculator,
93 | $name = null
94 | ) {
95 | parent::__construct($name);
96 | $this->timer = $timer;
97 | $this->customerIdsProvider = $customerIdsProvider;
98 | $this->loop = $loopFactory::create();
99 | $this->clientFactory = $clientFactory;
100 | $this->jsonHandler = $jsonHandler;
101 | $this->storeManager = $storeManager;
102 | $this->chunkSizeCalculator = $chunkSizeCalculator;
103 | }
104 |
105 | /**
106 | * {@inheritdoc}
107 | */
108 | protected function configure()
109 | {
110 | $this->setName(self::COMMAND_NAME)
111 | ->setDescription(self::COMMAND_DESCRIPTION)
112 | ->addArgument(
113 | self::ARGUMENT_NUMBER_OF_THREADS,
114 | InputArgument::REQUIRED,
115 | 'Number of threads for running the export process'
116 | );
117 | }
118 |
119 | /**
120 | * @param InputInterface $input
121 | * @param OutputInterface $output
122 | * @return void
123 | */
124 | protected function execute(InputInterface $input, OutputInterface $output)
125 | {
126 | $customerIds = $this->customerIdsProvider->getCustomerIds();
127 | $numberOfThreads = (int)$input->getArgument(self::ARGUMENT_NUMBER_OF_THREADS);
128 |
129 | $this->timer->startTimer();
130 |
131 | $this->startProcesses($customerIds, $numberOfThreads);
132 |
133 | $this->timer->stopTimer();
134 |
135 | $output->writeln("Process finished after {$this->timer->getExecutionTimeInSeconds()} seconds");
136 | }
137 |
138 | /**
139 | * @param array $customerIds
140 | * @param int $numberOfThreads
141 | */
142 | protected function startProcesses(array $customerIds, int $numberOfThreads): void
143 | {
144 | $chunkSize = $this->chunkSizeCalculator->calculateChunkSize($customerIds, $numberOfThreads);
145 | $threadedCustomerIds = array_chunk($customerIds, $chunkSize);
146 | foreach ($threadedCustomerIds as $customerIdsForSingleThread) {
147 | $this->createRequestDefinition($customerIdsForSingleThread);
148 | }
149 | $this->loop->run();
150 | }
151 |
152 | /**
153 | * @param int[] $customerIds
154 | */
155 | protected function createRequestDefinition(array $customerIds): void
156 | {
157 | $client = $this->clientFactory->create($this->loop);
158 | $data = $this->jsonHandler->serialize(['customerIds' => $customerIds]);
159 | $request = $client->request(
160 | 'POST',
161 | $this->getRequestUrl(),
162 | [
163 | 'Content-Type' => 'application/json',
164 | 'Content-Length' => strlen($data)
165 | ]
166 | );
167 | $request->write($data);
168 | $request->on('response', function (Response $response) use (&$htmlObjectArray) {
169 | $data = '';
170 | $response->on(
171 | 'data',
172 | function ($chunk) use (&$data) {
173 | $data .= $chunk;
174 | }
175 | )->on(
176 | 'end',
177 | function () use (&$data) {
178 | foreach ($this->jsonHandler->unserialize($data) as $message) {
179 | echo $message;
180 | }
181 | }
182 | );
183 | });
184 | $request->end();
185 | }
186 |
187 | /**
188 | * @return string
189 | */
190 | protected function getRequestUrl(): string
191 | {
192 | return $this->storeManager->getStore()->getBaseUrl() . self::API_ENDPOINT_PATH;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/Exception/TimerException.php:
--------------------------------------------------------------------------------
1 |
6 | * Github: https://github.com/maciejslawik
7 | */
8 |
9 | namespace MSlwk\ReactPhpPlayground\Exception;
10 |
11 | use Exception;
12 |
13 | /**
14 | * Class TimerException
15 | * @package MSlwk\ReactPhpPlayground\Exception
16 | */
17 | class TimerException extends Exception
18 | {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Maciej Sławik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Model/Adapter/ReactPHP/ClientFactory.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP;
12 |
13 | use React\EventLoop\LoopInterface;
14 | use React\HttpClient\Client;
15 |
16 | /**
17 | * Class ClientFactory
18 | * @package MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP
19 | */
20 | class ClientFactory
21 | {
22 | /**
23 | * @param LoopInterface $loop
24 | * @return Client
25 | */
26 | public function create(LoopInterface $loop): Client
27 | {
28 | return new Client($loop);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Model/Adapter/ReactPHP/ProcessFactory.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP;
12 |
13 | use React\ChildProcess\Process;
14 |
15 | /**
16 | * Class ProcessFactory
17 | * @package MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP
18 | */
19 | class ProcessFactory
20 | {
21 | /**
22 | * @param string $command
23 | * @return Process
24 | */
25 | public function create(string $command): Process
26 | {
27 | return new Process($command);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Model/ChunkSizeCalculator.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\ChunkSizeCalculatorInterface;
14 |
15 | /**
16 | * Class ChunkSizeCalculator
17 | * @package MSlwk\ReactPhpPlayground\Model
18 | */
19 | class ChunkSizeCalculator implements ChunkSizeCalculatorInterface
20 | {
21 | /**
22 | * @param array $elements
23 | * @param int $numberOfParts
24 | * @return int
25 | */
26 | public function calculateChunkSize(array $elements, int $numberOfParts): int
27 | {
28 | $numberOfChunks = (int)ceil(count($elements) / $numberOfParts);
29 | return $numberOfChunks > 0 ? $numberOfChunks : 1;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Model/Data/Html.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Data;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 |
15 | /**
16 | * Class Html
17 | * @package MSlwk\ReactPhpPlayground\Model\Data
18 | */
19 | class Html implements HtmlInterface
20 | {
21 | /**
22 | * @var string
23 | */
24 | private $html;
25 |
26 | /**
27 | * Html constructor.
28 | * @param string $html
29 | */
30 | public function __construct(string $html)
31 | {
32 | $this->html = $html;
33 | }
34 |
35 | /**
36 | * @return string
37 | */
38 | public function getHtml(): string
39 | {
40 | return $this->html;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Model/Data/Process.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 |
12 | namespace MSlwk\ReactPhpPlayground\Model\Data;
13 |
14 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
15 |
16 | /**
17 | * Class Process
18 | * @package MSlwk\ReactPhpPlayground\Model\Data
19 | */
20 | class Process implements ProcessInterface
21 | {
22 | /**
23 | * @var string
24 | */
25 | private $command;
26 |
27 | /**
28 | * Process constructor.
29 | * @param string $command
30 | */
31 | public function __construct(string $command)
32 | {
33 | $this->command = $command;
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getCommand(): string
40 | {
41 | return $this->command;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Model/Data/Url.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Data;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
14 |
15 | /**
16 | * Class Url
17 | * @package MSlwk\ReactPhpPlayground\Model\Data
18 | */
19 | class Url implements UrlInterface
20 | {
21 | /**
22 | * @var string
23 | */
24 | private $url;
25 |
26 | /**
27 | * Url constructor.
28 | * @param string $url
29 | */
30 | public function __construct(string $url)
31 | {
32 | $this->url = $url;
33 | }
34 |
35 | /**
36 | * @return string
37 | */
38 | public function getUrl(): string
39 | {
40 | return $this->url;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Model/FakeCustomerIdsProvider.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\CustomerIdsProviderInterface;
14 |
15 | /**
16 | * Class FakeCustomerIdsProvider
17 | * @package MSlwk\ReactPhpPlayground\Model
18 | */
19 | class FakeCustomerIdsProvider implements CustomerIdsProviderInterface
20 | {
21 | /**
22 | * @return int[]
23 | */
24 | public function getCustomerIds(): array
25 | {
26 | return [
27 | 1,
28 | 2,
29 | 3,
30 | 4,
31 | 5,
32 | 6,
33 | 7,
34 | 8
35 | ];
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Model/Report/CliReportManager.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportGeneratorInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Report\CliReportManagerInterface;
15 | use MSlwk\ReactPhpPlayground\Api\Report\ReportSenderInterface;
16 |
17 | /**
18 | * Class CliReportManager
19 | * @package MSlwk\ReactPhpPlayground\Model\Report
20 | */
21 | class CliReportManager implements CliReportManagerInterface
22 | {
23 | /**
24 | * @var ReportGeneratorInterface
25 | */
26 | private $reportGenerator;
27 |
28 | /**
29 | * @var ReportSenderInterface
30 | */
31 | private $reportSender;
32 |
33 | /**
34 | * CliReportManager constructor.
35 | * @param ReportGeneratorInterface $reportGenerator
36 | * @param ReportSenderInterface $reportSender
37 | */
38 | public function __construct(
39 | ReportGeneratorInterface $reportGenerator,
40 | ReportSenderInterface $reportSender
41 | ) {
42 | $this->reportGenerator = $reportGenerator;
43 | $this->reportSender = $reportSender;
44 | }
45 |
46 | /**
47 | * @param int[] $customerIds
48 | * @return void
49 | */
50 | public function generateAndSendReportForCustomers(array $customerIds): void
51 | {
52 | foreach ($customerIds as $customerId) {
53 | $report = $this->reportGenerator->generateReport($customerId);
54 | $this->reportSender->sendReport($report);
55 | echo "Reporting process finished for customer: {$customerId}\n";
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Model/Report/ReportGenerator.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportGeneratorInterface;
14 |
15 | /**
16 | * Class ReportGenerator
17 | * @package MSlwk\ReactPhpPlayground\Model\Report
18 | */
19 | class ReportGenerator implements ReportGeneratorInterface
20 | {
21 | /**
22 | * @param int $customerId
23 | * @return string
24 | * @codeCoverageIgnore
25 | */
26 | public function generateReport(int $customerId): string
27 | {
28 | /**
29 | * Report is being generated
30 | */
31 | $loopSize = 31500;
32 |
33 | $primes = [];
34 |
35 | for ($i = 2; $i < $loopSize; $i++) {
36 | for ($j = 2; $j < $i; $j++) {
37 | if ($i % $j == 0) {
38 | break;
39 | }
40 | }
41 | if ($i === $j) {
42 | $primes[] = $i;
43 | }
44 | }
45 |
46 | return '';
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Model/Report/ReportSender.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportSenderInterface;
14 |
15 | /**
16 | * Class ReportSender
17 | * @package MSlwk\ReactPhpPlayground\Model\Report
18 | */
19 | class ReportSender implements ReportSenderInterface
20 | {
21 | /**
22 | * @param string $report
23 | * @return void
24 | * @codeCoverageIgnore
25 | */
26 | public function sendReport(string $report): void
27 | {
28 | /**
29 | * Report is being sent, waiting for 3rd-party service
30 | */
31 | sleep(1);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Model/Report/WebapiReportManager.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportGeneratorInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Report\WebapiReportManagerInterface;
15 | use MSlwk\ReactPhpPlayground\Api\Report\ReportSenderInterface;
16 |
17 | /**
18 | * Class WebapiReportManager
19 | * @package MSlwk\ReactPhpPlayground\Model\Report
20 | */
21 | class WebapiReportManager implements WebapiReportManagerInterface
22 | {
23 | /**
24 | * @var ReportGeneratorInterface
25 | */
26 | private $reportGenerator;
27 |
28 | /**
29 | * @var ReportSenderInterface
30 | */
31 | private $reportSender;
32 |
33 | /**
34 | * WebapiReportManager constructor.
35 | * @param ReportGeneratorInterface $reportGenerator
36 | * @param ReportSenderInterface $reportSender
37 | */
38 | public function __construct(
39 | ReportGeneratorInterface $reportGenerator,
40 | ReportSenderInterface $reportSender
41 | ) {
42 | $this->reportGenerator = $reportGenerator;
43 | $this->reportSender = $reportSender;
44 | }
45 |
46 | /**
47 | * @param int[] $customerIds
48 | * @return string[]
49 | */
50 | public function generateAndSendReportForCustomers(array $customerIds): array
51 | {
52 | $messages = [];
53 | foreach ($customerIds as $customerId) {
54 | $report = $this->reportGenerator->generateReport($customerId);
55 | $this->reportSender->sendReport($report);
56 | $messages[] = "Reporting process finished for customer: {$customerId}\n";
57 | }
58 | return $messages;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Model/Timer.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\TimerInterface;
14 | use MSlwk\ReactPhpPlayground\Exception\TimerException;
15 |
16 | /**
17 | * Class Timer
18 | * @package MSlwk\ReactPhpPlayground\Model
19 | */
20 | class Timer implements TimerInterface
21 | {
22 | /**
23 | * @var float
24 | */
25 | private $timeStart = 0.0;
26 |
27 | /**
28 | * @var float
29 | */
30 | private $timeStop = 0.0;
31 |
32 | /**
33 | * @return void
34 | */
35 | public function startTimer(): void
36 | {
37 | $this->timeStart = microtime(true);
38 | }
39 |
40 | /**
41 | * @return void
42 | * @throws TimerException
43 | */
44 | public function stopTimer(): void
45 | {
46 | if (!$this->timeStart) {
47 | throw new TimerException('Timer not started');
48 | }
49 | $this->timeStop = microtime(true);
50 | }
51 |
52 | /**
53 | * @return float
54 | * @throws TimerException
55 | */
56 | public function getExecutionTimeInSeconds(): float
57 | {
58 | if (!$this->timeStart || !$this->timeStop) {
59 | throw new TimerException('Execution time cannot be calculated');
60 | }
61 | $executionTime = $this->timeStop - $this->timeStart;
62 | $this->timeStart = 0.0;
63 | $this->timeStop = 0.0;
64 | return $executionTime;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://scrutinizer-ci.com/g/maciejslawik/reactphp-playground-magento2/build-status/master)
2 | [](https://scrutinizer-ci.com/g/maciejslawik/reactphp-playground-magento2/?branch=master)
3 | [](https://packagist.org/packages/mslwk/module-reactphp-playground)
4 | [](https://packagist.org/packages/mslwk/module-reactphp-playground)
5 | [](https://packagist.org/packages/mslwk/module-reactphp-playground)
6 |
7 | # Magento 2 ReactPHP Playground #
8 |
9 | Magento 2 module which showcases how to run resource-heavy processes asynchronously using
10 | multiple threads with ReactPHP ChildProcess and HttpClient libraries.
11 |
12 | ## Prerequisites ##
13 |
14 | * Magento 2.2 or higher
15 | * PHP 7.1
16 |
17 | ## Installing ##
18 |
19 | You can install the module by downloading a .zip file and unpacking it inside
20 | ``app/code/MSlwk/ReactPhpPlayground`` directory inside your Magento
21 | or via Composer (recommended).
22 |
23 | To install the module via Composer simply run
24 | ```
25 | composer require mslwk/module-reactphp-playground
26 | ```
27 |
28 | Than enable the module by running these command in the root of your Magento installation
29 | ```
30 | bin/magento module:enable MSlwk_ReactPhpPlayground
31 | bin/magento setup:upgrade
32 | ```
33 |
34 | ## Usage ##
35 |
36 | #### Non-Magento scripts ####
37 |
38 | The module contains PHP CLI scripts which don't require Magento. They present the potential differences
39 | between the same calculations run on 1, 2 and 4 threads.
40 |
41 | * To run HttpClient example start the ``Standalone/bin/http`` script
42 | * To run ChildProcess example start the ``Standalone/bin/childprocess`` script
43 |
44 | #### Magento commands ####
45 |
46 | The module contains 2 commands available via ``bin/magento``. You can choose the number of threads to use.
47 |
48 | * To run HttpClient example use
49 | ```
50 | bin/magento mslwk:webapi-reporting-start <>
51 | ```
52 |
53 | * To run ChildProcess example use
54 | ```
55 | bin/magento mslwk:cli-reporting-start <>
56 | ```
57 |
58 | ## Authors
59 |
60 | * **Maciej Sławik** - https://github.com/maciejslawik
61 |
62 | ## License
63 |
64 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
65 |
66 | ## Screenshots
67 |
68 | 
69 |
70 | 
71 |
72 | 
--------------------------------------------------------------------------------
/Standalone/ChildProcess/AsynchronousProcessRunner.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\ChildProcess;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
14 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
15 | use MSlwk\TypeSafeArray\ObjectArray;
16 | use React\EventLoop\LoopInterface;
17 |
18 | /**
19 | * Class AsynchronousProcessRunner
20 | * @package MSlwk\ReactPhpPlayground\Standalone\ChildProcess
21 | */
22 | class AsynchronousProcessRunner implements ProcessRunnerInterface
23 | {
24 | /**
25 | * @var LoopInterface
26 | */
27 | private $loop;
28 |
29 | /**
30 | * @var ProcessFactory
31 | */
32 | private $processFactory;
33 |
34 | /**
35 | * AsynchronousProcessRunner constructor.
36 | * @param LoopInterface $loop
37 | * @param ProcessFactory $processFactory
38 | */
39 | public function __construct(
40 | LoopInterface $loop,
41 | ProcessFactory $processFactory
42 | ) {
43 | $this->loop = $loop;
44 | $this->processFactory = $processFactory;
45 | }
46 |
47 | /**
48 | * @param ObjectArray $processes
49 | * @return void
50 | */
51 | public function runProcesses(ObjectArray $processes): void
52 | {
53 | /** @var ProcessInterface $process */
54 | foreach ($processes as $process) {
55 | $this->createProcessDefinition($process);
56 | }
57 | $this->loop->run();
58 | }
59 |
60 | /**
61 | * @codeCoverageIgnore
62 | * @param ProcessInterface $process
63 | * @return void
64 | */
65 | protected function createProcessDefinition(ProcessInterface $process): void
66 | {
67 | $reactProcess = $this->processFactory->create($process->getCommand());
68 | $reactProcess->start($this->loop);
69 |
70 | $reactProcess->stdout->on('data', function ($chunk) {
71 | echo $chunk;
72 | });
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/HalfAsynchronousProcessRunner.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 |
12 | namespace MSlwk\ReactPhpPlayground\Standalone\ChildProcess;
13 |
14 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
16 | use MSlwk\TypeSafeArray\ObjectArray;
17 | use React\EventLoop\LoopInterface;
18 |
19 | /**
20 | * Class HalfAsynchronousProcessRunner
21 | * @package MSlwk\ReactPhpPlayground\Standalone\ChildProcess
22 | */
23 | class HalfAsynchronousProcessRunner implements ProcessRunnerInterface
24 | {
25 | /**
26 | * @var LoopInterface
27 | */
28 | private $loop;
29 |
30 | /**
31 | * @var ProcessFactory
32 | */
33 | private $processFactory;
34 |
35 | /**
36 | * AsynchronousProcessRunner constructor.
37 | * @param LoopInterface $loop
38 | * @param ProcessFactory $processFactory
39 | */
40 | public function __construct(
41 | LoopInterface $loop,
42 | ProcessFactory $processFactory
43 | ) {
44 | $this->loop = $loop;
45 | $this->processFactory = $processFactory;
46 | }
47 |
48 | /**
49 | * @param ObjectArray $processes
50 | * @return void
51 | */
52 | public function runProcesses(ObjectArray $processes): void
53 | {
54 | for ($i = 0; $i < ($processes->count() / 2); $i++) {
55 | $this->createProcessDefinition($processes->offsetGet($i));
56 | }
57 | $this->loop->run();
58 |
59 | for ($i; $i < ($processes->count()); $i++) {
60 | $this->createProcessDefinition($processes->offsetGet($i));
61 | }
62 | $this->loop->run();
63 | }
64 |
65 | /**
66 | * @codeCoverageIgnore
67 | * @param ProcessInterface $process
68 | * @return void
69 | */
70 | protected function createProcessDefinition(ProcessInterface $process): void
71 | {
72 | $reactProcess = $this->processFactory->create($process->getCommand());
73 | $reactProcess->start($this->loop);
74 |
75 | $reactProcess->stdout->on('data', function ($chunk) {
76 | echo $chunk;
77 | });
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/ProcessRunnerInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\ChildProcess;
12 |
13 | use MSlwk\TypeSafeArray\ObjectArray;
14 |
15 | /**
16 | * Interface ProcessRunnerInterface
17 | * @package MSlwk\ReactPhpPlayground\Standalone\ChildProcess
18 | */
19 | interface ProcessRunnerInterface
20 | {
21 | /**
22 | * @param ObjectArray $processes
23 | * @return void
24 | */
25 | public function runProcesses(ObjectArray $processes): void;
26 | }
27 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/SynchronousProcessRunner.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\ChildProcess;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
14 | use MSlwk\TypeSafeArray\ObjectArray;
15 |
16 | /**
17 | * Class SynchronousProcessRunner
18 | * @package MSlwk\ReactPhpPlayground\Standalone\ChildProcess
19 | */
20 | class SynchronousProcessRunner implements ProcessRunnerInterface
21 | {
22 | /**
23 | * @param ObjectArray $processes
24 | * @return void
25 | */
26 | public function runProcesses(ObjectArray $processes): void
27 | {
28 | /** @var ProcessInterface $process */
29 | foreach ($processes as $process) {
30 | $output = $this->execWrapper($process->getCommand());
31 | echo $output . PHP_EOL;
32 | }
33 | }
34 |
35 | /**
36 | * @codeCoverageIgnore
37 | * @param string $command
38 | * @return string
39 | */
40 | protected function execWrapper(string $command): string
41 | {
42 | return exec($command);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/processes/pi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 |
13 | $pi = 4;
14 | $top = 4;
15 | $bottom = 3;
16 | $minus = true;
17 | $accuracy = 50000000;
18 |
19 | for ($i = 0; $i < $accuracy; $i++) {
20 | $pi += ($minus ? -($top / $bottom) : ($top / $bottom));
21 | $minus = ($minus ? false : true);
22 | $bottom += 2;
23 | }
24 |
25 | echo 'Pi ~= ' . $pi . PHP_EOL;
26 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/processes/primes:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 | $loopSize = 70000;
13 |
14 | $primes = [];
15 |
16 | for ($i = 2; $i < $loopSize; $i++) {
17 | for ($j = 2; $j < $i; $j++) {
18 | if ($i % $j == 0) {
19 | break;
20 | }
21 | }
22 | if ($i === $j) {
23 | $primes[] = $i;
24 | }
25 | }
26 |
27 | echo 'Primes found: ' . count($primes) . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/processes/random:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 | $loopSize = 50000000;
13 |
14 | for ($i = 0; $i < $loopSize; $i++) {
15 | rand();
16 | }
17 |
18 | echo 'Randomizer run 50000000 times' . PHP_EOL;
19 |
--------------------------------------------------------------------------------
/Standalone/ChildProcess/processes/sleep:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 | sleep(3);
13 |
14 | echo 'Slept 3 seconds' . PHP_EOL;
15 |
--------------------------------------------------------------------------------
/Standalone/Http/AsynchronousClient.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Html;
16 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
17 | use MSlwk\TypeSafeArray\ObjectArray;
18 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
19 | use React\EventLoop\LoopInterface;
20 | use React\HttpClient\Response;
21 |
22 | /**
23 | * Class AsynchronousClient
24 | * @package MSlwk\ReactPhpPlayground\Standalone\Http
25 | */
26 | class AsynchronousClient implements ClientInterface
27 | {
28 | /**
29 | * @var LoopInterface
30 | */
31 | private $loop;
32 |
33 | /**
34 | * @var ClientFactory
35 | */
36 | private $clientFactory;
37 |
38 | /**
39 | * @var ObjectArrayFactory
40 | */
41 | private $objectArrayFactory;
42 |
43 | /**
44 | * AsynchronousClient constructor.
45 | * @param LoopInterface $loop
46 | * @param ClientFactory $clientFactory
47 | * @param ObjectArrayFactory $objectArrayFactory
48 | */
49 | public function __construct(
50 | LoopInterface $loop,
51 | ClientFactory $clientFactory,
52 | ObjectArrayFactory $objectArrayFactory
53 | ) {
54 | $this->loop = $loop;
55 | $this->clientFactory = $clientFactory;
56 | $this->objectArrayFactory = $objectArrayFactory;
57 | }
58 |
59 | /**
60 | * @param ObjectArray $urls
61 | * @return ObjectArray
62 | */
63 | public function getContent(ObjectArray $urls): ObjectArray
64 | {
65 | $htmlObjectArray = $this->objectArrayFactory->create(HtmlInterface::class);
66 | /** @var UrlInterface $url */
67 | foreach ($urls as $url) {
68 | $this->createRequestDefinition($url, $htmlObjectArray);
69 | }
70 | $this->loop->run();
71 | return $htmlObjectArray;
72 | }
73 |
74 | /**
75 | * @codeCoverageIgnore
76 | * @param UrlInterface $url
77 | * @param ObjectArray $htmlObjectArray
78 | * @return void
79 | */
80 | private function createRequestDefinition(UrlInterface $url, ObjectArray &$htmlObjectArray): void
81 | {
82 | $client = $this->clientFactory->create($this->loop);
83 | $request = $client->request('GET', $url->getUrl());
84 | $request->on('response', function (Response $response) use (&$htmlObjectArray) {
85 | $data = '';
86 | $response->on(
87 | 'data',
88 | function ($chunk) use (&$data) {
89 | $data .= $chunk;
90 | }
91 | )->on(
92 | 'end',
93 | function () use (&$htmlObjectArray, &$data) {
94 | $htmlObjectArray->add(new Html($data));
95 | }
96 | );
97 | });
98 | $request->end();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Standalone/Http/ClientInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\Http;
12 |
13 | use MSlwk\TypeSafeArray\ObjectArray;
14 |
15 | /**
16 | * Interface ClientInterface
17 | * @package MSlwk\ReactPhpPlayground\Standalone\Http
18 | */
19 | interface ClientInterface
20 | {
21 | /**
22 | * @param ObjectArray $urls
23 | * @return ObjectArray
24 | */
25 | public function getContent(ObjectArray $urls): ObjectArray;
26 | }
27 |
--------------------------------------------------------------------------------
/Standalone/Http/HalfAsynchronousClient.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Html;
16 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
17 | use MSlwk\TypeSafeArray\ObjectArray;
18 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
19 | use React\EventLoop\LoopInterface;
20 | use React\HttpClient\Response;
21 |
22 | /**
23 | * Class HalfAsynchronousClient
24 | * @package MSlwk\ReactPhpPlayground\Standalone\Http
25 | */
26 | class HalfAsynchronousClient implements ClientInterface
27 | {
28 | /**
29 | * @var LoopInterface
30 | */
31 | private $loop;
32 |
33 | /**
34 | * @var ClientFactory
35 | */
36 | private $clientFactory;
37 |
38 | /**
39 | * @var ObjectArrayFactory
40 | */
41 | private $objectArrayFactory;
42 |
43 | /**
44 | * HalfAsynchronousClient constructor.
45 | * @param LoopInterface $loop
46 | * @param ClientFactory $clientFactory
47 | * @param ObjectArrayFactory $objectArrayFactory
48 | */
49 | public function __construct(
50 | LoopInterface $loop,
51 | ClientFactory $clientFactory,
52 | ObjectArrayFactory $objectArrayFactory
53 | ) {
54 | $this->loop = $loop;
55 | $this->clientFactory = $clientFactory;
56 | $this->objectArrayFactory = $objectArrayFactory;
57 | }
58 |
59 | /**
60 | * @param ObjectArray $urls
61 | * @return ObjectArray
62 | */
63 | public function getContent(ObjectArray $urls): ObjectArray
64 | {
65 | $htmlObjectArray = $this->objectArrayFactory->create(HtmlInterface::class);
66 |
67 | for ($i = 0; $i < ($urls->count() / 2); $i++) {
68 | $this->createRequestDefinition($urls->offsetGet($i), $htmlObjectArray);
69 | }
70 | $this->loop->run();
71 |
72 | for ($i; $i < ($urls->count()); $i++) {
73 | $this->createRequestDefinition($urls->offsetGet($i), $htmlObjectArray);
74 | }
75 | $this->loop->run();
76 |
77 | return $htmlObjectArray;
78 | }
79 |
80 | /**
81 | * @codeCoverageIgnore
82 | * @param UrlInterface $url
83 | * @param ObjectArray $htmlObjectArray
84 | * @return void
85 | */
86 | private function createRequestDefinition(UrlInterface $url, ObjectArray &$htmlObjectArray): void
87 | {
88 | $client = $this->clientFactory->create($this->loop);
89 | $request = $client->request('GET', $url->getUrl());
90 | $request->on('response', function (Response $response) use (&$htmlObjectArray) {
91 | $data = '';
92 | $response->on(
93 | 'data',
94 | function ($chunk) use (&$data) {
95 | $data .= $chunk;
96 | }
97 | )->on(
98 | 'end',
99 | function () use (&$htmlObjectArray, &$data) {
100 | $htmlObjectArray->add(new Html($data));
101 | }
102 | );
103 | });
104 | $request->end();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Standalone/Http/SynchronousClient.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Html;
16 | use MSlwk\TypeSafeArray\ObjectArray;
17 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
18 |
19 | /**
20 | * Class SynchronousClient
21 | * @package MSlwk\ReactPhpPlayground\Standalone\Http
22 | */
23 | class SynchronousClient implements ClientInterface
24 | {
25 | /**
26 | * @var ObjectArrayFactory
27 | */
28 | private $objectArrayFactory;
29 |
30 | /**
31 | * SynchronousClient constructor.
32 | * @param ObjectArrayFactory $objectArrayFactory
33 | */
34 | public function __construct(ObjectArrayFactory $objectArrayFactory)
35 | {
36 | $this->objectArrayFactory = $objectArrayFactory;
37 | }
38 |
39 | /**
40 | * @param ObjectArray $urls
41 | * @return ObjectArray
42 | */
43 | public function getContent(ObjectArray $urls): ObjectArray
44 | {
45 | $htmlObjectArray = $this->objectArrayFactory->create(HtmlInterface::class);
46 | /** @var UrlInterface $url */
47 | foreach ($urls as $url) {
48 | $html = $this->fileGetContentsWrapper($url);
49 | $htmlObjectArray->add(new Html($html));
50 | }
51 | return $htmlObjectArray;
52 | }
53 |
54 | /**
55 | * @codeCoverageIgnore
56 | * @param UrlInterface $url
57 | * @return bool|string
58 | */
59 | protected function fileGetContentsWrapper(UrlInterface $url)
60 | {
61 | $html = file_get_contents($url->getUrl());
62 | return $html;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Standalone/Http/UrlProvider.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
14 | use MSlwk\ReactPhpPlayground\Model\Data\Url;
15 | use MSlwk\TypeSafeArray\ObjectArray;
16 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
17 |
18 | /**
19 | * Trait UrlProvider
20 | * @package MSlwk\ReactPhpPlayground\Standalone\Http
21 | */
22 | class UrlProvider
23 | {
24 | /**
25 | * @var ObjectArrayFactory
26 | */
27 | private $objectArrayFactory;
28 |
29 | /**
30 | * UrlProvider constructor.
31 | * @param ObjectArrayFactory $objectArrayFactory
32 | */
33 | public function __construct(ObjectArrayFactory $objectArrayFactory)
34 | {
35 | $this->objectArrayFactory = $objectArrayFactory;
36 | }
37 |
38 | /**
39 | * @return ObjectArray
40 | */
41 | public function getUrls(): ObjectArray
42 | {
43 | $urls = [
44 | 'https://magento.com',
45 | 'https://marketplace.magento.com',
46 | 'https://u.magento.com',
47 | 'https://devdocs.magento.com',
48 | 'https://github.com/magento/magento2',
49 | 'https://pl.meet-magento.com/pl/'
50 | ];
51 |
52 | $urlObjectArray = $this->objectArrayFactory->create(UrlInterface::class);
53 | foreach ($urls as $url) {
54 | $urlObjectArray->add(new Url($url));
55 | }
56 | return $urlObjectArray;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Standalone/bin/childprocess:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
13 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
14 | use MSlwk\ReactPhpPlayground\Model\Data\Process;
15 | use MSlwk\ReactPhpPlayground\Model\Timer;
16 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\AsynchronousProcessRunner;
17 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\HalfAsynchronousProcessRunner;
18 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\ProcessRunnerInterface;
19 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\SynchronousProcessRunner;
20 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
21 | use React\EventLoop\Factory;
22 |
23 | require_once __DIR__ . '/../../../../../../vendor/autoload.php';
24 |
25 | $objectArrayFactory = new ObjectArrayFactory();
26 | $timer = new Timer();
27 | $processFactory = new ProcessFactory();
28 | $loop = Factory::create();
29 |
30 | $synchronousRunner = new SynchronousProcessRunner();
31 | $halfAsynchronousRunner = new HalfAsynchronousProcessRunner($loop, $processFactory);
32 | $asynchronousRunner = new AsynchronousProcessRunner($loop, $processFactory);
33 |
34 | $processes = $objectArrayFactory->create(ProcessInterface::class);
35 | $processes->add(new Process(__DIR__ . '/../ChildProcess/processes/pi'));
36 | $processes->add(new Process(__DIR__ . '/../ChildProcess/processes/primes'));
37 | $processes->add(new Process(__DIR__ . '/../ChildProcess/processes/random'));
38 | $processes->add(new Process(__DIR__ . '/../ChildProcess/processes/sleep'));
39 |
40 | $runners = [
41 | $synchronousRunner,
42 | $halfAsynchronousRunner,
43 | $asynchronousRunner
44 | ];
45 |
46 | /** @var ProcessRunnerInterface $runner */
47 | foreach ($runners as $runner) {
48 | $timer->startTimer();
49 | $runner->runProcesses($processes);
50 | $timer->stopTimer();
51 | echo '--------------------------------------------------------------------------------------------------' . PHP_EOL;
52 | echo "\033[0;32mExecution time for "
53 | . get_class($runner)
54 | . ': '
55 | . $timer->getExecutionTimeInSeconds()
56 | . " seconds\033[0m"
57 | . PHP_EOL;
58 | }
59 |
--------------------------------------------------------------------------------
/Standalone/bin/http:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
9 | * Github: https://github.com/maciejslawik
10 | */
11 |
12 | use MSlwk\ReactPhpPlayground\Model\Timer;
13 | use MSlwk\ReactPhpPlayground\Standalone\Http\AsynchronousClient;
14 | use MSlwk\ReactPhpPlayground\Standalone\Http\ClientInterface;
15 | use MSlwk\ReactPhpPlayground\Standalone\Http\HalfAsynchronousClient;
16 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
17 | use MSlwk\ReactPhpPlayground\Standalone\Http\SynchronousClient;
18 | use MSlwk\ReactPhpPlayground\Standalone\Http\UrlProvider;
19 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
20 | use React\EventLoop\Factory;
21 |
22 | require_once __DIR__ . '/../../../../../../vendor/autoload.php';
23 |
24 | $objectArrayFactory = new ObjectArrayFactory();
25 | $urlProvider = new UrlProvider($objectArrayFactory);
26 | $clientFactory = new ClientFactory();
27 | $synchronousClient = new SynchronousClient($objectArrayFactory);
28 | $halfAsynchronousClient = new HalfAsynchronousClient(Factory::create(), $clientFactory, $objectArrayFactory);
29 | $asynchronousClient = new AsynchronousClient(Factory::create(), $clientFactory, $objectArrayFactory);
30 | $timer = new Timer();
31 |
32 | $clients = $objectArrayFactory->create(
33 | ClientInterface::class,
34 | [
35 | $synchronousClient,
36 | $halfAsynchronousClient,
37 | $asynchronousClient
38 | ]
39 | );
40 |
41 | /** @var ClientInterface $client */
42 | foreach ($clients as $client) {
43 | $timer->startTimer();
44 | $htmls = $client->getContent($urlProvider->getUrls());
45 | $timer->stopTimer();
46 | echo '--------------------------------------------------------------------------------------------------' . PHP_EOL;
47 | echo "\033[0;32mExecution time for "
48 | . get_class($client)
49 | . ': '
50 | . $timer->getExecutionTimeInSeconds()
51 | . " seconds\033[0m"
52 | . PHP_EOL;
53 | }
54 |
--------------------------------------------------------------------------------
/Test/Unit/Console/Command/GenerateReportsTest.php:
--------------------------------------------------------------------------------
1 |
7 | * Github: https://github.com/maciejslawik
8 | */
9 |
10 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Console\Command;
11 |
12 | use MSlwk\ReactPhpPlayground\Console\Command\GenerateReports;
13 | use PHPUnit\Framework\TestCase;
14 | use Magento\Framework\Serialize\Serializer\Json;
15 | use MSlwk\ReactPhpPlayground\Api\Report\CliReportManagerInterface;
16 | use ReflectionClass;
17 | use Symfony\Component\Console\Input\InputInterface;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 | use PHPUnit_Framework_MockObject_MockObject;
20 |
21 | /**
22 | * Class GenerateReportsTest
23 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Console\Command
24 | */
25 | class GenerateReportsTest extends TestCase
26 | {
27 | /**
28 | * @var PHPUnit_Framework_MockObject_MockObject|Json
29 | */
30 | private $jsonHandler;
31 |
32 | /**
33 | * @var PHPUnit_Framework_MockObject_MockObject|CliReportManagerInterface
34 | */
35 | private $reportManager;
36 |
37 | /**
38 | * @var PHPUnit_Framework_MockObject_MockObject|InputInterface
39 | */
40 | private $input;
41 |
42 | /**
43 | * @var PHPUnit_Framework_MockObject_MockObject|OutputInterface
44 | */
45 | private $output;
46 |
47 | /**
48 | * @var GenerateReports
49 | */
50 | private $command;
51 |
52 | /**
53 | * @return void
54 | */
55 | protected function setUp()
56 | {
57 | $this->jsonHandler = $this->getMockBuilder(Json::class)
58 | ->disableOriginalConstructor()
59 | ->getMock();
60 | $this->reportManager = $this->getMockBuilder(CliReportManagerInterface::class)
61 | ->getMock();
62 | $this->input = $this->getMockBuilder(InputInterface::class)
63 | ->getMock();
64 | $this->output = $this->getMockBuilder(OutputInterface::class)
65 | ->getMock();
66 |
67 | $this->command = new GenerateReports(
68 | $this->jsonHandler,
69 | $this->reportManager
70 | );
71 | }
72 |
73 | /**
74 | * @test
75 | */
76 | public function testCommandHasCorrectName()
77 | {
78 | $this->assertEquals(GenerateReports::COMMAND_NAME, $this->command->getName());
79 | }
80 |
81 | /**
82 | * @test
83 | */
84 | public function testCommandHasCorrectDescription()
85 | {
86 | $this->assertEquals(GenerateReports::COMMAND_DESCRIPTION, $this->command->getDescription());
87 | }
88 |
89 | /**
90 | * @test
91 | */
92 | public function testExecute()
93 | {
94 | $customerIds = [1, 2];
95 | $this->input->expects($this->once())
96 | ->method('getArgument')
97 | ->with(GenerateReports::ARGUMENT_CUSTOMER_IDS)
98 | ->willReturn('json');
99 | $this->jsonHandler->expects($this->once())
100 | ->method('unserialize')
101 | ->with('json')
102 | ->willReturn($customerIds);
103 | $this->reportManager->expects($this->once())
104 | ->method('generateAndSendReportForCustomers')
105 | ->with($customerIds);
106 |
107 | $reflection = new ReflectionClass(get_class($this->command));
108 | $method = $reflection->getMethod('execute');
109 | $method->setAccessible(true);
110 | $method->invokeArgs($this->command, [$this->input, $this->output]);
111 |
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Test/Unit/Console/Command/StartCliReportingServiceTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Console\Command;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\ChunkSizeCalculatorInterface;
14 | use MSlwk\ReactPhpPlayground\Console\Command\StartCliReportingService;
15 | use PHPUnit\Framework\TestCase;
16 | use Magento\Framework\Serialize\Serializer\Json;
17 | use PHPUnit_Framework_MockObject_MockObject;
18 | use MSlwk\ReactPhpPlayground\Api\CustomerIdsProviderInterface;
19 | use MSlwk\ReactPhpPlayground\Api\TimerInterface;
20 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
21 | use React\EventLoop\Factory;
22 |
23 | /**
24 | * Class StartCliReportingServiceTest
25 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Console\Command
26 | */
27 | class StartCliReportingServiceTest extends TestCase
28 | {
29 | /**
30 | * @var StartCliReportingService
31 | */
32 | private $command;
33 |
34 | /**
35 | * @return void
36 | */
37 | protected function setUp()
38 | {
39 | /** @var PHPUnit_Framework_MockObject_MockObject|TimerInterface $timer */
40 | $timer = $this->getMockBuilder(TimerInterface::class)
41 | ->getMock();
42 | /** @var PHPUnit_Framework_MockObject_MockObject|CustomerIdsProviderInterface $customerIdsProvider */
43 | $customerIdsProvider = $this->getMockBuilder(CustomerIdsProviderInterface::class)
44 | ->getMock();
45 | $loopFactory = new Factory();
46 | /** @var PHPUnit_Framework_MockObject_MockObject|ProcessFactory $processFactory */
47 | $processFactory = $this->getMockBuilder(ProcessFactory::class)
48 | ->disableOriginalConstructor()
49 | ->getMock();
50 | /** @var PHPUnit_Framework_MockObject_MockObject|Json $jsonHandler */
51 | $jsonHandler = $this->getMockBuilder(Json::class)
52 | ->disableOriginalConstructor()
53 | ->getMock();
54 | /** @var PHPUnit_Framework_MockObject_MockObject|ChunkSizeCalculatorInterface $chunkSizeCalculator */
55 | $chunkSizeCalculator = $this->getMockBuilder(ChunkSizeCalculatorInterface::class)
56 | ->getMock();
57 |
58 | $this->command = new StartCliReportingService(
59 | $timer,
60 | $customerIdsProvider,
61 | $loopFactory,
62 | $processFactory,
63 | $jsonHandler,
64 | $chunkSizeCalculator
65 | );
66 | }
67 |
68 | /**
69 | * @test
70 | */
71 | public function testCommandHasCorrectName()
72 | {
73 | $this->assertEquals(StartCliReportingService::COMMAND_NAME, $this->command->getName());
74 | }
75 |
76 | /**
77 | * @test
78 | */
79 | public function testCommandHasCorrectDescription()
80 | {
81 | $this->assertEquals(StartCliReportingService::COMMAND_DESCRIPTION, $this->command->getDescription());
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Test/Unit/Console/Command/StartWebapiReportingServiceTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Console\Command;
12 |
13 | use Magento\Store\Model\StoreManagerInterface;
14 | use MSlwk\ReactPhpPlayground\Api\ChunkSizeCalculatorInterface;
15 | use MSlwk\ReactPhpPlayground\Console\Command\StartWebapiReportingService;
16 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
17 | use PHPUnit\Framework\TestCase;
18 | use Magento\Framework\Serialize\Serializer\Json;
19 | use PHPUnit_Framework_MockObject_MockObject;
20 | use MSlwk\ReactPhpPlayground\Api\CustomerIdsProviderInterface;
21 | use MSlwk\ReactPhpPlayground\Api\TimerInterface;
22 | use React\EventLoop\Factory;
23 |
24 | /**
25 | * Class StartWebapiReportingServiceTest
26 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Console\Command
27 | */
28 | class StartWebapiReportingServiceTest extends TestCase
29 | {
30 | /**
31 | * @var StartWebapiReportingService
32 | */
33 | private $command;
34 |
35 | /**
36 | * @return void
37 | */
38 | protected function setUp()
39 | {
40 | /** @var PHPUnit_Framework_MockObject_MockObject|TimerInterface $timer */
41 | $timer = $this->getMockBuilder(TimerInterface::class)
42 | ->getMock();
43 | /** @var PHPUnit_Framework_MockObject_MockObject|CustomerIdsProviderInterface $customerIdsProvider */
44 | $customerIdsProvider = $this->getMockBuilder(CustomerIdsProviderInterface::class)
45 | ->getMock();
46 | $loopFactory = new Factory();
47 | /** @var PHPUnit_Framework_MockObject_MockObject|ClientFactory $clientFactory */
48 | $clientFactory = $this->getMockBuilder(ClientFactory::class)
49 | ->disableOriginalConstructor()
50 | ->getMock();
51 | /** @var PHPUnit_Framework_MockObject_MockObject|Json $jsonHandler */
52 | $jsonHandler = $this->getMockBuilder(Json::class)
53 | ->disableOriginalConstructor()
54 | ->getMock();
55 | /** @var PHPUnit_Framework_MockObject_MockObject|StoreManagerInterface $storeManager */
56 | $storeManager = $this->getMockBuilder(StoreManagerInterface::class)
57 | ->getMock();
58 | /** @var PHPUnit_Framework_MockObject_MockObject|ChunkSizeCalculatorInterface $chunkSizeCalculator */
59 | $chunkSizeCalculator = $this->getMockBuilder(ChunkSizeCalculatorInterface::class)
60 | ->getMock();
61 |
62 | $this->command = new StartWebapiReportingService(
63 | $timer,
64 | $customerIdsProvider,
65 | $loopFactory,
66 | $clientFactory,
67 | $jsonHandler,
68 | $storeManager,
69 | $chunkSizeCalculator
70 | );
71 | }
72 |
73 | /**
74 | * @test
75 | */
76 | public function testCommandHasCorrectName()
77 | {
78 | $this->assertEquals(StartWebapiReportingService::COMMAND_NAME, $this->command->getName());
79 | }
80 |
81 | /**
82 | * @test
83 | */
84 | public function testCommandHasCorrectDescription()
85 | {
86 | $this->assertEquals(StartWebapiReportingService::COMMAND_DESCRIPTION, $this->command->getDescription());
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Adapter/ReactPHP/ClientFactoryTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Adapter\ReactPHP;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
14 | use PHPUnit\Framework\TestCase;
15 | use React\EventLoop\LoopInterface;
16 | use React\HttpClient\Client;
17 |
18 | /**
19 | * Class ClientFactoryTest
20 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Adapter\ReactPHP
21 | */
22 | class ClientFactoryTest extends TestCase
23 | {
24 | /**
25 | * @test
26 | */
27 | public function testFactoryReturnsCorrectObject()
28 | {
29 | $loop = $this->getMockBuilder(LoopInterface::class)
30 | ->getMock();
31 | $factory = new ClientFactory();
32 |
33 | $result = $factory->create($loop);
34 |
35 | $this->assertInstanceOf(Client::class, $result);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Adapter/ReactPHP/ProcessFactoryTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Adapter\ReactPHP;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
14 | use PHPUnit\Framework\TestCase;
15 | use React\ChildProcess\Process;
16 |
17 | /**
18 | * Class ProcessFactoryTest
19 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Adapter\ReactPHP
20 | */
21 | class ProcessFactoryTest extends TestCase
22 | {
23 | /**
24 | * @test
25 | */
26 | public function testFactoryReturnsCorrectObject()
27 | {
28 | $command = 'ps aux';
29 | $factory = new ProcessFactory();
30 |
31 | $result = $factory->create($command);
32 |
33 | $this->assertInstanceOf(Process::class, $result);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Test/Unit/Model/ChunkSizeCalculatorTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\ChunkSizeCalculator;
14 | use PHPUnit\Framework\TestCase;
15 |
16 | /**
17 | * Class ChunkSizeCalculatorTest
18 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model
19 | */
20 | class ChunkSizeCalculatorTest extends TestCase
21 | {
22 | /**
23 | * @test
24 | * @param array $elements
25 | * @param int $numberOfThreads
26 | * @param int $expected
27 | * @dataProvider chunksDataProvider
28 | */
29 | public function testCalculateNumberOfChunks(array $elements, int $numberOfThreads, int $expected)
30 | {
31 | $calculator = new ChunkSizeCalculator();
32 |
33 | $this->assertEquals($expected, $calculator->calculateChunkSize($elements, $numberOfThreads));
34 | }
35 |
36 | /**
37 | * @return array
38 | */
39 | public function chunksDataProvider()
40 | {
41 | return [
42 | [
43 | [
44 | 1,
45 | 2,
46 | 3,
47 | 4,
48 | 5,
49 | 6,
50 | 7
51 | ],
52 | 3,
53 | 3
54 | ],
55 | [
56 | [
57 | 1,
58 | 2,
59 | 3,
60 | 4,
61 | 5,
62 | 6
63 | ],
64 | 5,
65 | 2
66 | ],
67 | [
68 | [
69 | 1,
70 | 2,
71 | 3
72 | ],
73 | 5,
74 | 1
75 | ]
76 | ];
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Data/HtmlTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Data;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\Data\Html;
14 | use PHPUnit\Framework\TestCase;
15 |
16 | /**
17 | * Class HtmlTest
18 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Data
19 | */
20 | class HtmlTest extends TestCase
21 | {
22 | /**
23 | * @test
24 | */
25 | public function testGetHtml()
26 | {
27 | $html = '';
28 | $htmlObject = new Html($html);
29 |
30 | $this->assertEquals($html, $htmlObject->getHtml());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Data/ProcessTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Data;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\Data\Process;
14 | use PHPUnit\Framework\TestCase;
15 |
16 | /**
17 | * Class ProcessTest
18 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Data
19 | */
20 | class ProcessTest extends TestCase
21 | {
22 | /**
23 | * @test
24 | */
25 | public function testGetCommand()
26 | {
27 | $command = 'ps aux';
28 | $commandObject = new Process($command);
29 |
30 | $this->assertEquals($command, $commandObject->getCommand());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Data/UrlTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Data;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\Data\Url;
14 | use PHPUnit\Framework\TestCase;
15 |
16 | /**
17 | * Class UrlTest
18 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Data
19 | */
20 | class UrlTest extends TestCase
21 | {
22 | /**
23 | * @test
24 | */
25 | public function testGetUrl()
26 | {
27 | $url = 'https://magento.com';
28 | $urlObject = new Url($url);
29 |
30 | $this->assertEquals($url, $urlObject->getUrl());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Test/Unit/Model/FakeCustomerIdsProviderTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Model\FakeCustomerIdsProvider;
14 | use PHPUnit\Framework\TestCase;
15 |
16 | /**
17 | * Class FakeCustomerIdsProviderTest
18 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model
19 | */
20 | class FakeCustomerIdsProviderTest extends TestCase
21 | {
22 | /**
23 | * @test
24 | */
25 | public function testProviderReturnsArrayOfInts()
26 | {
27 | $idsProvider = new FakeCustomerIdsProvider();
28 | $result = $idsProvider->getCustomerIds();
29 |
30 | foreach ($result as $id) {
31 | $this->assertInternalType('int', $id);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Report/CliReportManagerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportGeneratorInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Report\ReportSenderInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Report\CliReportManager;
16 | use PHPUnit\Framework\TestCase;
17 | use PHPUnit_Framework_MockObject_MockObject;
18 |
19 | /**
20 | * Class CliReportManagerTest
21 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Report
22 | */
23 | class CliReportManagerTest extends TestCase
24 | {
25 | /**
26 | * @var PHPUnit_Framework_MockObject_MockObject|ReportGeneratorInterface
27 | */
28 | private $reportGenerator;
29 |
30 | /**
31 | * @var PHPUnit_Framework_MockObject_MockObject|ReportSenderInterface
32 | */
33 | private $reportSender;
34 |
35 | /**
36 | * @var CliReportManager
37 | */
38 | private $reportManager;
39 |
40 | /**
41 | * @return void
42 | */
43 | protected function setUp()
44 | {
45 | $this->reportGenerator = $this->getMockBuilder(ReportGeneratorInterface::class)
46 | ->getMock();
47 | $this->reportSender = $this->getMockBuilder(ReportSenderInterface::class)
48 | ->getMock();
49 |
50 | $this->reportManager = new CliReportManager(
51 | $this->reportGenerator,
52 | $this->reportSender
53 | );
54 | }
55 |
56 | /**
57 | * @test
58 | */
59 | public function testSendAndGenerateReports()
60 | {
61 | $customerIds = [
62 | 1,
63 | 2,
64 | 3
65 | ];
66 | $report = 'report';
67 | $this->reportGenerator->expects($this->exactly(3))
68 | ->method('generateReport')
69 | ->withConsecutive([1], [2], [3])
70 | ->willReturn($report);
71 | $this->reportSender->expects($this->exactly(3))
72 | ->method('sendReport')
73 | ->with($report);
74 |
75 | $this->reportManager->generateAndSendReportForCustomers($customerIds);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Test/Unit/Model/Report/WebapiReportManagerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * Github: https://github.com/maciejslawik
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model\Report;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Report\ReportGeneratorInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Report\ReportSenderInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Report\WebapiReportManager;
16 | use PHPUnit\Framework\TestCase;
17 | use PHPUnit_Framework_MockObject_MockObject;
18 |
19 | /**
20 | * Class WebapiReportManagerTest
21 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model\Report
22 | */
23 | class WebapiReportManagerTest extends TestCase
24 | {
25 | /**
26 | * @var PHPUnit_Framework_MockObject_MockObject|ReportGeneratorInterface
27 | */
28 | private $reportGenerator;
29 |
30 | /**
31 | * @var PHPUnit_Framework_MockObject_MockObject|ReportSenderInterface
32 | */
33 | private $reportSender;
34 |
35 | /**
36 | * @var WebapiReportManager
37 | */
38 | private $reportManager;
39 |
40 | /**
41 | * @return void
42 | */
43 | protected function setUp()
44 | {
45 | $this->reportGenerator = $this->getMockBuilder(ReportGeneratorInterface::class)
46 | ->getMock();
47 | $this->reportSender = $this->getMockBuilder(ReportSenderInterface::class)
48 | ->getMock();
49 |
50 | $this->reportManager = new WebapiReportManager(
51 | $this->reportGenerator,
52 | $this->reportSender
53 | );
54 | }
55 |
56 | /**
57 | * @test
58 | */
59 | public function testSendAndGenerateReports()
60 | {
61 | $customerIds = [
62 | 1,
63 | 2,
64 | 3
65 | ];
66 | $report = 'report';
67 | $this->reportGenerator->expects($this->exactly(3))
68 | ->method('generateReport')
69 | ->withConsecutive([1], [2], [3])
70 | ->willReturn($report);
71 | $this->reportSender->expects($this->exactly(3))
72 | ->method('sendReport')
73 | ->with($report);
74 |
75 | $result = $this->reportManager->generateAndSendReportForCustomers($customerIds);
76 |
77 | $this->assertEquals(3, count($result));
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Test/Unit/Model/TimerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Model;
12 |
13 | use MSlwk\ReactPhpPlayground\Exception\TimerException;
14 | use MSlwk\ReactPhpPlayground\Model\Timer;
15 | use PHPUnit\Framework\TestCase;
16 |
17 | /**
18 | * Class TimerTest
19 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Model
20 | */
21 | class TimerTest extends TestCase
22 | {
23 | /**
24 | * @var Timer
25 | */
26 | private $timer;
27 |
28 | /**
29 | * @return void
30 | */
31 | protected function setUp()
32 | {
33 | $this->timer = new Timer();
34 | }
35 |
36 | /**
37 | * @test
38 | * @throws TimerException
39 | */
40 | public function testTimerCalculatesEexecutionTime()
41 | {
42 | $this->timer->startTimer();
43 | $this->timer->stopTimer();
44 |
45 | $this->assertGreaterThan(0.0, $this->timer->getExecutionTimeInSeconds());
46 | }
47 |
48 | /**
49 | * @test
50 | * @throws TimerException
51 | */
52 | public function testCannotStopTimerWithoutStarting()
53 | {
54 | $this->expectException(TimerException::class);
55 | $this->timer->stopTimer();
56 | }
57 |
58 | /**
59 | * @test
60 | * @throws TimerException
61 | */
62 | public function testCannotCalculateTimeWithoutStartingTimer()
63 | {
64 | $this->expectException(TimerException::class);
65 | $this->timer->getExecutionTimeInSeconds();
66 | }
67 |
68 | /**
69 | * @test
70 | * @throws TimerException
71 | */
72 | public function testCannotCalculateTimeWithoutStoppingTimer()
73 | {
74 | $this->expectException(TimerException::class);
75 | $this->timer->startTimer();
76 | $this->timer->getExecutionTimeInSeconds();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/ChildProcess/AsynchronousProcessRunnerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
14 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Process;
16 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\AsynchronousProcessRunner;
17 | use MSlwk\TypeSafeArray\ObjectArray;
18 | use PHPUnit\Framework\TestCase;
19 | use PHPUnit_Framework_MockObject_MockObject;
20 | use React\EventLoop\LoopInterface;
21 |
22 | /**
23 | * Class AsynchronousProcessRunnerTest
24 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess
25 | */
26 | class AsynchronousProcessRunnerTest extends TestCase
27 | {
28 | /**
29 | * @var PHPUnit_Framework_MockObject_MockObject|LoopInterface
30 | */
31 | private $loop;
32 |
33 | /**
34 | * @var PHPUnit_Framework_MockObject_MockObject|ProcessFactory
35 | */
36 | private $processFactory;
37 |
38 | /**
39 | * @var PHPUnit_Framework_MockObject_MockObject|AsynchronousProcessRunner
40 | */
41 | private $asynchronousRunner;
42 |
43 | /**
44 | * @return void
45 | */
46 | protected function setUp()
47 | {
48 | $this->loop = $this->getMockBuilder(LoopInterface::class)
49 | ->getMock();
50 | $this->processFactory = $this->getMockBuilder(ProcessFactory::class)
51 | ->disableOriginalConstructor()
52 | ->getMock();
53 |
54 | $this->asynchronousRunner = $this->getMockBuilder(AsynchronousProcessRunner::class)
55 | ->setConstructorArgs(
56 | [
57 | 'loop' => $this->loop,
58 | 'processFactory' => $this->processFactory
59 | ]
60 | )
61 | ->setMethods(['createProcessDefinition'])
62 | ->getMock();
63 | }
64 |
65 | /**
66 | * @test
67 | */
68 | public function testRunProcesses()
69 | {
70 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $processArray */
71 | $processArray = $this->getMockBuilder(ObjectArray::class)
72 | ->setConstructorArgs(
73 | [
74 | 'type' => ProcessInterface::class,
75 | 'objects' => [new Process('process'), new Process('process')]
76 | ]
77 | )
78 | ->setMethods(null)
79 | ->getMock();
80 |
81 | $this->asynchronousRunner->expects($this->exactly(2))
82 | ->method('createProcessDefinition');
83 | $this->loop->expects($this->once())
84 | ->method('run');
85 |
86 | $this->asynchronousRunner->runProcesses($processArray);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/ChildProcess/HalfAsynchronousProcessRunnerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
14 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ProcessFactory;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Process;
16 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\HalfAsynchronousProcessRunner;
17 | use MSlwk\TypeSafeArray\ObjectArray;
18 | use PHPUnit\Framework\TestCase;
19 | use PHPUnit_Framework_MockObject_MockObject;
20 | use React\EventLoop\LoopInterface;
21 |
22 | /**
23 | * Class HalfAsynchronousProcessRunnerTest
24 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess
25 | */
26 | class HalfAsynchronousProcessRunnerTest extends TestCase
27 | {
28 | /**
29 | * @var PHPUnit_Framework_MockObject_MockObject|LoopInterface
30 | */
31 | private $loop;
32 |
33 | /**
34 | * @var PHPUnit_Framework_MockObject_MockObject|ProcessFactory
35 | */
36 | private $processFactory;
37 |
38 | /**
39 | * @var PHPUnit_Framework_MockObject_MockObject|HalfAsynchronousProcessRunner
40 | */
41 | private $halfAsynchronousRunner;
42 |
43 | /**
44 | * @return void
45 | */
46 | protected function setUp()
47 | {
48 | $this->loop = $this->getMockBuilder(LoopInterface::class)
49 | ->getMock();
50 | $this->processFactory = $this->getMockBuilder(ProcessFactory::class)
51 | ->disableOriginalConstructor()
52 | ->getMock();
53 |
54 | $this->halfAsynchronousRunner = $this->getMockBuilder(HalfAsynchronousProcessRunner::class)
55 | ->setConstructorArgs(
56 | [
57 | 'loop' => $this->loop,
58 | 'processFactory' => $this->processFactory
59 | ]
60 | )
61 | ->setMethods(['createProcessDefinition'])
62 | ->getMock();
63 | }
64 |
65 | /**
66 | * @test
67 | */
68 | public function testRunProcesses()
69 | {
70 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $processArray */
71 | $processArray = $this->getMockBuilder(ObjectArray::class)
72 | ->setConstructorArgs(
73 | [
74 | 'type' => ProcessInterface::class,
75 | 'objects' => [new Process('process'), new Process('process')]
76 | ]
77 | )
78 | ->setMethods(null)
79 | ->getMock();
80 |
81 | $this->halfAsynchronousRunner->expects($this->exactly(2))
82 | ->method('createProcessDefinition');
83 | $this->loop->expects($this->exactly(2))
84 | ->method('run');
85 |
86 | $this->halfAsynchronousRunner->runProcesses($processArray);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/ChildProcess/SynchronousProcessRunnerTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\ProcessInterface;
14 | use MSlwk\ReactPhpPlayground\Model\Data\Process;
15 | use MSlwk\ReactPhpPlayground\Standalone\ChildProcess\SynchronousProcessRunner;
16 | use MSlwk\TypeSafeArray\ObjectArray;
17 | use PHPUnit\Framework\TestCase;
18 | use PHPUnit_Framework_MockObject_MockObject;
19 |
20 | /**
21 | * Class SynchronousProcessRunnerTest
22 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\ChildProcess
23 | */
24 | class SynchronousProcessRunnerTest extends TestCase
25 | {
26 | /**
27 | * @test
28 | */
29 | public function testRunProcesses()
30 | {
31 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $processArray */
32 | $processArray = $this->getMockBuilder(ObjectArray::class)
33 | ->setConstructorArgs(
34 | [
35 | 'type' => ProcessInterface::class,
36 | 'objects' => [new Process('process')]
37 | ]
38 | )
39 | ->setMethods(null)
40 | ->getMock();
41 | /** @var PHPUnit_Framework_MockObject_MockObject|SynchronousProcessRunner $synchronousRunner */
42 | $synchronousRunner = $this->getMockBuilder(SynchronousProcessRunner::class)
43 | ->disableOriginalConstructor()
44 | ->setMethods(['execWrapper'])
45 | ->getMock();
46 | $synchronousRunner->expects($this->once())
47 | ->method('execWrapper')
48 | ->with('process')
49 | ->willReturn('');
50 |
51 | $synchronousRunner->runProcesses($processArray);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/Http/AsynchronousClientTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
16 | use MSlwk\ReactPhpPlayground\Model\Data\Url;
17 | use MSlwk\ReactPhpPlayground\Standalone\Http\AsynchronousClient;
18 | use MSlwk\TypeSafeArray\ObjectArray;
19 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
20 | use PHPUnit\Framework\TestCase;
21 | use PHPUnit_Framework_MockObject_MockObject;
22 | use React\EventLoop\LoopInterface;
23 | use React\HttpClient\Client;
24 | use React\HttpClient\Request;
25 |
26 | /**
27 | * Class AsynchronousClientTest
28 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http
29 | */
30 | class AsynchronousClientTest extends TestCase
31 | {
32 | /**
33 | * @var PHPUnit_Framework_MockObject_MockObject|LoopInterface
34 | */
35 | private $loop;
36 |
37 | /**
38 | * @var PHPUnit_Framework_MockObject_MockObject|ClientFactory
39 | */
40 | private $clientFactory;
41 |
42 | /**
43 | * @var PHPUnit_Framework_MockObject_MockObject|ObjectArrayFactory
44 | */
45 | private $objectArrayFactory;
46 |
47 | /**
48 | * @var AsynchronousClient
49 | */
50 | private $asynchronousClient;
51 |
52 | /**
53 | * @return void
54 | */
55 | protected function setUp()
56 | {
57 | $this->loop = $this->getMockBuilder(LoopInterface::class)
58 | ->getMock();
59 | $this->clientFactory = $this->getMockBuilder(ClientFactory::class)
60 | ->disableOriginalConstructor()
61 | ->getMock();
62 | $this->objectArrayFactory = $this->getMockBuilder(ObjectArrayFactory::class)
63 | ->disableOriginalConstructor()
64 | ->getMock();
65 |
66 | $this->asynchronousClient = new AsynchronousClient(
67 | $this->loop,
68 | $this->clientFactory,
69 | $this->objectArrayFactory
70 | );
71 | }
72 |
73 | /**
74 | * @test
75 | */
76 | public function testGetContent()
77 | {
78 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $htmlObjectArray */
79 | $htmlObjectArray = $this->getMockBuilder(ObjectArray::class)
80 | ->setConstructorArgs(
81 | [
82 | 'type' => HtmlInterface::class
83 | ]
84 | )
85 | ->setMethods(null)
86 | ->getMock();
87 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $urlObjectArray */
88 | $urlObjectArray = $this->getMockBuilder(ObjectArray::class)
89 | ->setConstructorArgs(
90 | [
91 | 'type' => UrlInterface::class,
92 | 'objects' => [new Url('url')]
93 | ]
94 | )
95 | ->setMethods(null)
96 | ->getMock();
97 | $this->objectArrayFactory->expects($this->once())
98 | ->method('create')
99 | ->willReturn($htmlObjectArray);
100 | $client = $this->getMockBuilder(Client::class)
101 | ->disableOriginalConstructor()
102 | ->getMock();
103 | $this->clientFactory->expects($this->once())
104 | ->method('create')
105 | ->with($this->loop)
106 | ->willReturn($client);
107 | $request = $this->getMockBuilder(Request::class)
108 | ->disableOriginalConstructor()
109 | ->getMock();
110 | $client->expects($this->once())
111 | ->method('request')
112 | ->willReturn($request);
113 | $request->expects($this->once())
114 | ->method('end');
115 | $request->expects($this->once())
116 | ->method('on');
117 | $this->loop->expects($this->once())
118 | ->method('run');
119 |
120 | $result = $this->asynchronousClient->getContent($urlObjectArray);
121 |
122 | $this->assertInstanceOf(ObjectArray::class, $result);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/Http/HalfAsynchronousClientTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Adapter\ReactPHP\ClientFactory;
16 | use MSlwk\ReactPhpPlayground\Model\Data\Url;
17 | use MSlwk\ReactPhpPlayground\Standalone\Http\HalfAsynchronousClient;
18 | use MSlwk\TypeSafeArray\ObjectArray;
19 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
20 | use PHPUnit\Framework\TestCase;
21 | use PHPUnit_Framework_MockObject_MockObject;
22 | use React\EventLoop\LoopInterface;
23 | use React\HttpClient\Client;
24 | use React\HttpClient\Request;
25 |
26 | /**
27 | * Class HalfHalfAsynchronousClientTest
28 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http
29 | */
30 | class HalfHalfAsynchronousClientTest extends TestCase
31 | {
32 | /**
33 | * @var PHPUnit_Framework_MockObject_MockObject|LoopInterface
34 | */
35 | private $loop;
36 |
37 | /**
38 | * @var PHPUnit_Framework_MockObject_MockObject|ClientFactory
39 | */
40 | private $clientFactory;
41 |
42 | /**
43 | * @var PHPUnit_Framework_MockObject_MockObject|ObjectArrayFactory
44 | */
45 | private $objectArrayFactory;
46 |
47 | /**
48 | * @var HalfAsynchronousClient
49 | */
50 | private $halfHalfAsynchronousClient;
51 |
52 | /**
53 | * @return void
54 | */
55 | protected function setUp()
56 | {
57 | $this->loop = $this->getMockBuilder(LoopInterface::class)
58 | ->getMock();
59 | $this->clientFactory = $this->getMockBuilder(ClientFactory::class)
60 | ->disableOriginalConstructor()
61 | ->getMock();
62 | $this->objectArrayFactory = $this->getMockBuilder(ObjectArrayFactory::class)
63 | ->disableOriginalConstructor()
64 | ->getMock();
65 |
66 | $this->halfHalfAsynchronousClient = new HalfAsynchronousClient(
67 | $this->loop,
68 | $this->clientFactory,
69 | $this->objectArrayFactory
70 | );
71 | }
72 |
73 | /**
74 | * @test
75 | */
76 | public function testGetContent()
77 | {
78 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $htmlObjectArray */
79 | $htmlObjectArray = $this->getMockBuilder(ObjectArray::class)
80 | ->setConstructorArgs(
81 | [
82 | 'type' => HtmlInterface::class
83 | ]
84 | )
85 | ->setMethods(null)
86 | ->getMock();
87 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $urlObjectArray */
88 | $urlObjectArray = $this->getMockBuilder(ObjectArray::class)
89 | ->setConstructorArgs(
90 | [
91 | 'type' => UrlInterface::class,
92 | 'objects' => [new Url('url'), new Url('url')]
93 | ]
94 | )
95 | ->setMethods(null)
96 | ->getMock();
97 | $this->objectArrayFactory->expects($this->once())
98 | ->method('create')
99 | ->willReturn($htmlObjectArray);
100 | $client = $this->getMockBuilder(Client::class)
101 | ->disableOriginalConstructor()
102 | ->getMock();
103 | $this->clientFactory->expects($this->exactly(2))
104 | ->method('create')
105 | ->with($this->loop)
106 | ->willReturn($client);
107 | $request = $this->getMockBuilder(Request::class)
108 | ->disableOriginalConstructor()
109 | ->getMock();
110 | $client->expects($this->exactly(2))
111 | ->method('request')
112 | ->willReturn($request);
113 | $request->expects($this->exactly(2))
114 | ->method('end');
115 | $request->expects($this->exactly(2))
116 | ->method('on');
117 | $this->loop->expects($this->exactly(2))
118 | ->method('run');
119 |
120 | $result = $this->halfHalfAsynchronousClient->getContent($urlObjectArray);
121 |
122 | $this->assertInstanceOf(ObjectArray::class, $result);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/Http/SynchronousClientTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\HtmlInterface;
14 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
15 | use MSlwk\ReactPhpPlayground\Model\Data\Url;
16 | use MSlwk\ReactPhpPlayground\Standalone\Http\SynchronousClient;
17 | use MSlwk\TypeSafeArray\ObjectArray;
18 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
19 | use PHPUnit\Framework\TestCase;
20 | use PHPUnit_Framework_MockObject_MockObject;
21 |
22 | /**
23 | * Class SynchronousClientTest
24 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http
25 | */
26 | class SynchronousClientTest extends TestCase
27 | {
28 | /**
29 | * @test
30 | */
31 | public function testRun()
32 | {
33 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArrayFactory $objectArrayFactory */
34 | $objectArrayFactory = $this->getMockBuilder(ObjectArrayFactory::class)
35 | ->disableOriginalConstructor()
36 | ->getMock();
37 | $htmlObjectArray = $this->getMockBuilder(ObjectArray::class)
38 | ->setConstructorArgs(
39 | [
40 | 'type' => HtmlInterface::class
41 | ]
42 | )
43 | ->setMethods(null)
44 | ->getMock();
45 | $objectArrayFactory->expects($this->once())
46 | ->method('create')
47 | ->with(HtmlInterface::class)
48 | ->willReturn($htmlObjectArray);
49 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArray $urls */
50 | $urls = $this->getMockBuilder(ObjectArray::class)
51 | ->setConstructorArgs(
52 | [
53 | 'type' => UrlInterface::class,
54 | 'objects' => [
55 | new Url('')
56 | ]
57 | ]
58 | )
59 | ->setMethods(null)
60 | ->getMock();
61 |
62 | /** @var PHPUnit_Framework_MockObject_MockObject|SynchronousClient $runner */
63 | $runner = $this->getMockBuilder(SynchronousClient::class)
64 | ->setConstructorArgs(
65 | [
66 | 'objectArrayFactory' => $objectArrayFactory
67 | ]
68 | )
69 | ->setMethods(['fileGetContentsWrapper'])
70 | ->getMock();
71 | $runner->expects($this->once())
72 | ->method('fileGetContentsWrapper')
73 | ->willReturn('');
74 |
75 | $result = $runner->getContent($urls);
76 | $this->assertEquals(1, $result->count());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Test/Unit/Standalone/Http/UrlProviderTest.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
9 | */
10 |
11 | namespace MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http;
12 |
13 | use MSlwk\ReactPhpPlayground\Api\Data\UrlInterface;
14 | use MSlwk\ReactPhpPlayground\Standalone\Http\UrlProvider;
15 | use MSlwk\TypeSafeArray\ObjectArray;
16 | use MSlwk\TypeSafeArray\ObjectArrayFactory;
17 | use PHPUnit\Framework\TestCase;
18 | use PHPUnit_Framework_MockObject_MockObject;
19 |
20 | /**
21 | * Class UrlProviderTest
22 | * @package MSlwk\ReactPhpPlayground\Test\Unit\Standalone\Http
23 | */
24 | class UrlProviderTest extends TestCase
25 | {
26 | /**
27 | * @test
28 | */
29 | public function testGetUrls()
30 | {
31 | /** @var PHPUnit_Framework_MockObject_MockObject|ObjectArrayFactory $objectArrayFactory */
32 | $objectArrayFactory = $this->getMockBuilder(ObjectArrayFactory::class)
33 | ->disableOriginalConstructor()
34 | ->getMock();
35 | $urlProvider = new UrlProvider($objectArrayFactory);
36 |
37 | $objectArray = $this->getMockBuilder(ObjectArray::class)
38 | ->setConstructorArgs(
39 | [
40 | 'type' => UrlInterface::class
41 | ]
42 | )
43 | ->setMethods(null)
44 | ->getMock();
45 |
46 | $objectArrayFactory->expects($this->once())
47 | ->method('create')
48 | ->willReturn($objectArray);
49 |
50 | $result = $urlProvider->getUrls();
51 |
52 | $this->assertInstanceOf(ObjectArray::class, $result);
53 | $this->assertEquals(6, $result->count());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mslwk/module-reactphp-playground",
3 | "description": "ReactPHP playground module for Magento 2",
4 | "type": "magento2-module",
5 | "version": "1.0.0",
6 | "license": [
7 | "MIT"
8 | ],
9 | "authors": [
10 | {
11 | "name": "Maciej Sławik",
12 | "email": "maciekslawik@gmail.com"
13 | }
14 | ],
15 | "require": {
16 | "php": "^7.1.0",
17 | "magento/framework": ">=101.0.0",
18 | "magento/module-store": ">=100.0.0",
19 | "mslwk/php-typesafe-array": "^1.0",
20 | "react/http-client": "^0.5.9",
21 | "react/child-process": "^0.5.2"
22 | },
23 | "require-dev": {
24 | "phpunit/phpunit": ">=7.0.0"
25 | },
26 | "repositories": [
27 | {
28 | "type": "composer",
29 | "url": "https://repo.magento.com/"
30 | }
31 | ],
32 | "autoload": {
33 | "files": [
34 | "registration.php"
35 | ],
36 | "psr-4": {
37 | "MSlwk\\ReactPhpPlayground\\": ""
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/docs/magento_cli_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maciejslawik/reactphp-playground-magento2/9b637230792513b8fc01638f0629e9b3f19a25db/docs/magento_cli_1.png
--------------------------------------------------------------------------------
/docs/magento_cli_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maciejslawik/reactphp-playground-magento2/9b637230792513b8fc01638f0629e9b3f19a25db/docs/magento_cli_3.png
--------------------------------------------------------------------------------
/docs/standalone_cli.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maciejslawik/reactphp-playground-magento2/9b637230792513b8fc01638f0629e9b3f19a25db/docs/standalone_cli.png
--------------------------------------------------------------------------------
/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
11 |
13 |
15 |
17 |
19 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | - MSlwk\ReactPhpPlayground\Console\Command\GenerateReports
33 | - MSlwk\ReactPhpPlayground\Console\Command\StartCliReportingService
35 | - MSlwk\ReactPhpPlayground\Console\Command\StartWebapiReportingService
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | - Magento\Store\Model\StoreManagerInterface\Proxy
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/etc/webapi.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
6 | * Github: https://github.com/maciejslawik
7 | */
8 | \Magento\Framework\Component\ComponentRegistrar::register(
9 | \Magento\Framework\Component\ComponentRegistrar::MODULE,
10 | 'MSlwk_ReactPhpPlayground',
11 | __DIR__
12 | );
13 |
--------------------------------------------------------------------------------