Skip to content

Commit 3a8b2d6

Browse files
authored
Merge pull request #2350 from magento-engcom/async-bulk-webapi
[Engcom] Async bulk webapi
2 parents eb09566 + 7711351 commit 3a8b2d6

File tree

13 files changed

+848
-48
lines changed

13 files changed

+848
-48
lines changed

app/code/Magento/AsynchronousOperations/Model/MassSchedule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public function publishMass($topicName, array $entitiesArray, $groupId = null, $
110110
$requestItems = [];
111111
$bulkException = new BulkException();
112112
foreach ($entitiesArray as $key => $entityParams) {
113-
/** @var \Magento\WebapiAsync\Api\Data\ItemStatusInterface $requestItem */
113+
/** @var \Magento\AsynchronousOperations\Api\Data\ItemStatusInterface $requestItem */
114114
$requestItem = $this->itemStatusInterfaceFactory->create();
115115

116116
try {

app/code/Magento/Webapi/Model/Config.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @api
1818
* @since 100.0.2
1919
*/
20-
class Config
20+
class Config implements ConfigInterface
2121
{
2222
const CACHE_ID = 'webapi_config';
2323

@@ -66,9 +66,7 @@ public function __construct(
6666
}
6767

6868
/**
69-
* Return services loaded from cache if enabled or from files merged previously
70-
*
71-
* @return array
69+
* {@inheritdoc}
7270
*/
7371
public function getServices()
7472
{
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Webapi\Model;
10+
11+
/**
12+
* This class gives access to consolidated web API configuration from <Module_Name>/etc/webapi.xml files.
13+
*
14+
* @api
15+
*/
16+
interface ConfigInterface
17+
{
18+
/**
19+
* Return services loaded from cache if enabled or from files merged previously
20+
*
21+
* @return array
22+
*/
23+
public function getServices();
24+
}

app/code/Magento/Webapi/Model/Rest/Config.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Magento\Webapi\Model\Rest;
77

88
use Magento\Webapi\Controller\Rest\Router\Route;
9-
use Magento\Webapi\Model\Config as ModelConfig;
9+
use Magento\Webapi\Model\ConfigInterface as ModelConfigInterface;
1010
use Magento\Webapi\Model\Config\Converter;
1111

1212
/**
@@ -43,11 +43,13 @@ class Config
4343
protected $_routeFactory;
4444

4545
/**
46-
* @param ModelConfig $config
46+
* @param ModelConfigInterface $config
4747
* @param \Magento\Framework\Controller\Router\Route\Factory $routeFactory
4848
*/
49-
public function __construct(ModelConfig $config, \Magento\Framework\Controller\Router\Route\Factory $routeFactory)
50-
{
49+
public function __construct(
50+
ModelConfigInterface $config,
51+
\Magento\Framework\Controller\Router\Route\Factory $routeFactory
52+
) {
5153
$this->_config = $config;
5254
$this->_routeFactory = $routeFactory;
5355
}

app/code/Magento/Webapi/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<preference for="Magento\Webapi\Model\ConfigInterface" type="Magento\Webapi\Model\Config" />
910
<type name="Magento\Framework\App\AreaList">
1011
<arguments>
1112
<argument name="areas" xsi:type="array">
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\WebapiAsync\Controller\Rest\Asynchronous;
10+
11+
use Magento\Framework\Webapi\ServiceInputProcessor;
12+
use Magento\Framework\Webapi\Rest\Request as RestRequest;
13+
use Magento\Webapi\Controller\Rest\Router;
14+
use Magento\Webapi\Controller\Rest\ParamsOverrider;
15+
use Magento\Webapi\Controller\Rest\RequestValidator;
16+
use Magento\Webapi\Controller\Rest\InputParamsResolver as WebapiInputParamsResolver;
17+
18+
/**
19+
* This class is responsible for retrieving resolved input data
20+
*/
21+
class InputParamsResolver
22+
{
23+
/**
24+
* @var RestRequest
25+
*/
26+
private $request;
27+
/**
28+
* @var ParamsOverrider
29+
*/
30+
private $paramsOverrider;
31+
/**
32+
* @var ServiceInputProcessor
33+
*/
34+
private $serviceInputProcessor;
35+
/**
36+
* @var Router
37+
*/
38+
private $router;
39+
/**
40+
* @var RequestValidator
41+
*/
42+
private $requestValidator;
43+
/**
44+
* @var \Magento\Webapi\Controller\Rest\InputParamsResolver
45+
*/
46+
private $inputParamsResolver;
47+
/**
48+
* @var bool
49+
*/
50+
private $isBulk;
51+
52+
/**
53+
* Initialize dependencies.
54+
*
55+
* @param \Magento\Framework\Webapi\Rest\Request $request
56+
* @param \Magento\Webapi\Controller\Rest\ParamsOverrider $paramsOverrider
57+
* @param \Magento\Framework\Webapi\ServiceInputProcessor $inputProcessor
58+
* @param \Magento\Webapi\Controller\Rest\Router $router
59+
* @param \Magento\Webapi\Controller\Rest\RequestValidator $requestValidator
60+
* @param \Magento\Webapi\Controller\Rest\InputParamsResolver $inputParamsResolver
61+
* @param bool $isBulk
62+
*/
63+
public function __construct(
64+
RestRequest $request,
65+
ParamsOverrider $paramsOverrider,
66+
ServiceInputProcessor $inputProcessor,
67+
Router $router,
68+
RequestValidator $requestValidator,
69+
WebapiInputParamsResolver $inputParamsResolver,
70+
$isBulk = false
71+
) {
72+
$this->request = $request;
73+
$this->paramsOverrider = $paramsOverrider;
74+
$this->serviceInputProcessor = $inputProcessor;
75+
$this->router = $router;
76+
$this->requestValidator = $requestValidator;
77+
$this->inputParamsResolver = $inputParamsResolver;
78+
$this->isBulk = $isBulk;
79+
}
80+
81+
/**
82+
* Process and resolve input parameters
83+
* Return array with validated input params
84+
* or throw \Exception if at least one request entity params is not valid
85+
*
86+
* @return array
87+
* @throws \Magento\Framework\Exception\InputException if no value is provided for required parameters
88+
* @throws \Magento\Framework\Webapi\Exception
89+
*/
90+
public function resolve()
91+
{
92+
if ($this->isBulk === false) {
93+
return [$this->inputParamsResolver->resolve()];
94+
}
95+
$this->requestValidator->validate();
96+
$webapiResolvedParams = [];
97+
$inputData = $this->request->getRequestData();
98+
foreach ($inputData as $key => $singleEntityParams) {
99+
$webapiResolvedParams[$key] = $this->resolveBulkItemParams($singleEntityParams);
100+
}
101+
102+
return $webapiResolvedParams;
103+
}
104+
105+
/**
106+
* @return \Magento\Webapi\Controller\Rest\Router\Route
107+
*/
108+
public function getRoute()
109+
{
110+
return $this->inputParamsResolver->getRoute();
111+
}
112+
113+
/**
114+
* Convert the input array from key-value format to a list of parameters
115+
* suitable for the specified class / method.
116+
*
117+
* Instead of \Magento\Webapi\Controller\Rest\InputParamsResolver
118+
* we don't need to merge body params with url params and use only body params
119+
*
120+
* @param array $inputData data to send to method in key-value format
121+
* @return array list of parameters that can be used to call the service method
122+
* @throws \Magento\Framework\Exception\InputException if no value is provided for required parameters
123+
* @throws \Magento\Framework\Webapi\Exception
124+
*/
125+
private function resolveBulkItemParams($inputData)
126+
{
127+
$route = $this->getRoute();
128+
$serviceMethodName = $route->getServiceMethod();
129+
$serviceClassName = $route->getServiceClass();
130+
$inputParams = $this->serviceInputProcessor->process($serviceClassName, $serviceMethodName, $inputData);
131+
132+
return $inputParams;
133+
}
134+
}

app/code/Magento/WebapiAsync/Controller/Rest/AsynchronousRequestProcessor.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,51 @@
1111
use Magento\Framework\Exception\BulkException;
1212
use Magento\Webapi\Controller\Rest\RequestProcessorInterface;
1313
use Magento\Framework\Webapi\Rest\Response as RestResponse;
14-
use Magento\Webapi\Controller\Rest\InputParamsResolver;
14+
use Magento\WebapiAsync\Controller\Rest\Asynchronous\InputParamsResolver;
1515
use Magento\AsynchronousOperations\Model\MassSchedule;
1616
use Magento\AsynchronousOperations\Model\ConfigInterface as WebApiAsyncConfig;
1717
use Magento\Framework\Reflection\DataObjectProcessor;
1818
use Magento\AsynchronousOperations\Api\Data\AsyncResponseInterfaceFactory;
1919
use Magento\AsynchronousOperations\Api\Data\AsyncResponseInterface;
2020

21+
/**
22+
* Responsible for dispatching single and bulk requests.
23+
* Single requests dispatching represented by this class.
24+
* Bulk requests dispatching represented by virtualType of this class.
25+
*/
2126
class AsynchronousRequestProcessor implements RequestProcessorInterface
2227
{
2328
const PROCESSOR_PATH = "/^\\/async(\\/V.+)/";
29+
const BULK_PROCESSOR_PATH = "/^\\/async\/bulk(\\/V.+)/";
2430

2531
/**
2632
* @var \Magento\Framework\Webapi\Rest\Response
2733
*/
2834
private $response;
29-
3035
/**
31-
* @var InputParamsResolver
36+
* @var \Magento\WebapiAsync\Controller\Rest\Asynchronous\InputParamsResolver
3237
*/
3338
private $inputParamsResolver;
34-
3539
/**
3640
* @var MassSchedule
3741
*/
3842
private $asyncBulkPublisher;
39-
4043
/**
4144
* @var WebApiAsyncConfig
4245
*/
4346
private $webapiAsyncConfig;
44-
4547
/**
4648
* @var \Magento\Framework\Reflection\DataObjectProcessor
4749
*/
4850
private $dataObjectProcessor;
49-
5051
/**
5152
* @var AsyncResponseInterfaceFactory
5253
*/
5354
private $asyncResponseFactory;
55+
/**
56+
* @var string Regex pattern
57+
*/
58+
private $processorPath;
5459

5560
/**
5661
* Initialize dependencies.
@@ -61,21 +66,24 @@ class AsynchronousRequestProcessor implements RequestProcessorInterface
6166
* @param WebapiAsyncConfig $webapiAsyncConfig
6267
* @param DataObjectProcessor $dataObjectProcessor
6368
* @param AsyncResponseInterfaceFactory $asyncResponse
69+
* @param string $processorPath
6470
*/
6571
public function __construct(
6672
RestResponse $response,
6773
InputParamsResolver $inputParamsResolver,
6874
MassSchedule $asyncBulkPublisher,
6975
WebApiAsyncConfig $webapiAsyncConfig,
7076
DataObjectProcessor $dataObjectProcessor,
71-
AsyncResponseInterfaceFactory $asyncResponse
77+
AsyncResponseInterfaceFactory $asyncResponse,
78+
$processorPath = self::PROCESSOR_PATH
7279
) {
7380
$this->response = $response;
7481
$this->inputParamsResolver = $inputParamsResolver;
7582
$this->asyncBulkPublisher = $asyncBulkPublisher;
7683
$this->webapiAsyncConfig = $webapiAsyncConfig;
7784
$this->dataObjectProcessor = $dataObjectProcessor;
7885
$this->asyncResponseFactory = $asyncResponse;
86+
$this->processorPath = $processorPath;
7987
}
8088

8189
/**
@@ -84,12 +92,12 @@ public function __construct(
8492
public function process(\Magento\Framework\Webapi\Rest\Request $request)
8593
{
8694
$path = $request->getPathInfo();
87-
$path = preg_replace(self::PROCESSOR_PATH, "$1", $path);
95+
$path = preg_replace($this->processorPath, "$1", $path);
8896
$request->setPathInfo(
8997
$path
9098
);
9199

92-
$entitiesParamsArray = [$this->inputParamsResolver->resolve()];
100+
$entitiesParamsArray = $this->inputParamsResolver->resolve();
93101
$topicName = $this->getTopicName($request);
94102

95103
try {
@@ -133,7 +141,19 @@ public function canProcess(\Magento\Framework\Webapi\Rest\Request $request)
133141
return false;
134142
}
135143

136-
if (preg_match(self::PROCESSOR_PATH, $request->getPathInfo()) === 1) {
144+
if (preg_match($this->processorPath, $request->getPathInfo()) === 1) {
145+
return true;
146+
}
147+
return false;
148+
}
149+
150+
/**
151+
* @param \Magento\Framework\Webapi\Rest\Request $request
152+
* @return bool
153+
*/
154+
public function isBulk(\Magento\Framework\Webapi\Rest\Request $request)
155+
{
156+
if (preg_match(self::BULK_PROCESSOR_PATH, $request->getPathInfo()) === 1) {
137157
return true;
138158
}
139159
return false;

0 commit comments

Comments
 (0)