Skip to content

Commit 29a9c77

Browse files
committed
magento-engcom/bulk-api#4 Support for Async operations in WebAPI
- Separated Operations Status from the Status implementation for the legacy compativbility
1 parent 18628ba commit 29a9c77

File tree

3 files changed

+307
-107
lines changed

3 files changed

+307
-107
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\AsynchronousOperations\Model;
8+
9+
use Magento\AsynchronousOperations\Model\ResourceModel\Bulk\CollectionFactory as BulkCollectionFactory;
10+
use Magento\AsynchronousOperations\Model\ResourceModel\Operation\CollectionFactory as OperationCollectionFactory;
11+
use Magento\AsynchronousOperations\Api\Data\OperationInterface;
12+
use Magento\AsynchronousOperations\Api\Data\BulkSummaryInterface;
13+
use Magento\Framework\App\ResourceConnection;
14+
use Magento\AsynchronousOperations\Model\BulkStatus\CalculatedStatusSql;
15+
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Framework\Exception\NoSuchEntityException;
17+
use Magento\Framework\EntityManager\EntityManager;
18+
use Magento\AsynchronousOperations\Api\Data\BulkStatusInterfaceFactory as BulkStatusShortFactory;
19+
use Magento\AsynchronousOperations\Api\Data\DetailedBulkStatusInterfaceFactory as BulkStatusDetailedFactory;
20+
use Magento\AsynchronousOperations\Api\Data\OperationDetailsInterfaceFactory;
21+
use Magento\AsynchronousOperations\Api\BulkStatusInterface;
22+
23+
/**
24+
* Class BulkStatus
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26+
*/
27+
class BulkOperationsStatus implements BulkStatusInterface
28+
{
29+
/**
30+
* @var \Magento\AsynchronousOperations\Api\Data\BulkSummaryInterfaceFactory
31+
*/
32+
private $bulkCollectionFactory;
33+
34+
/**
35+
* @var \Magento\AsynchronousOperations\Api\Data\OperationInterfaceFactory
36+
*/
37+
private $operationCollectionFactory;
38+
39+
/**
40+
* @var ResourceConnection
41+
*/
42+
private $resourceConnection;
43+
44+
/**
45+
* @var CalculatedStatusSql
46+
*/
47+
private $calculatedStatusSql;
48+
49+
/**
50+
* @var MetadataPool
51+
*/
52+
private $metadataPool;
53+
54+
/**
55+
* @var EntityManager
56+
*/
57+
private $entityManager;
58+
59+
/**
60+
* @var BulkStatusDetailedFactory
61+
*/
62+
private $bulkDetailedFactory;
63+
64+
/**
65+
* @var BulkStatusShortFactory
66+
*/
67+
private $bulkShortFactory;
68+
69+
/**
70+
* Init dependencies.
71+
*
72+
* @param \Magento\AsynchronousOperations\Model\ResourceModel\Bulk\CollectionFactory $bulkCollection
73+
* @param \Magento\AsynchronousOperations\Model\ResourceModel\Operation\CollectionFactory $operationCollection
74+
* @param \Magento\Framework\App\ResourceConnection $resourceConnection
75+
* @param \Magento\AsynchronousOperations\Model\BulkStatus\CalculatedStatusSql $calculatedStatusSql
76+
* @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
77+
* @param BulkStatusDetailedFactory $bulkDetailedFactory
78+
* @param BulkStatusShortFactory $bulkShortFactory
79+
* @param \Magento\Framework\EntityManager\EntityManager $entityManager
80+
*/
81+
public function __construct(
82+
BulkCollectionFactory $bulkCollection,
83+
OperationCollectionFactory $operationCollection,
84+
ResourceConnection $resourceConnection,
85+
CalculatedStatusSql $calculatedStatusSql,
86+
MetadataPool $metadataPool,
87+
BulkStatusDetailedFactory $bulkDetailedFactory,
88+
BulkStatusShortFactory $bulkShortFactory,
89+
EntityManager $entityManager
90+
) {
91+
$this->operationCollectionFactory = $operationCollection;
92+
$this->bulkCollectionFactory = $bulkCollection;
93+
$this->resourceConnection = $resourceConnection;
94+
$this->calculatedStatusSql = $calculatedStatusSql;
95+
$this->metadataPool = $metadataPool;
96+
$this->bulkDetailedFactory = $bulkDetailedFactory;
97+
$this->bulkShortFactory = $bulkShortFactory;
98+
$this->entityManager = $entityManager;
99+
}
100+
101+
/**
102+
* @inheritDoc
103+
*/
104+
public function getFailedOperationsByBulkId($bulkUuid, $failureType = null)
105+
{
106+
$failureCodes = $failureType
107+
? [$failureType]
108+
: [
109+
OperationInterface::STATUS_TYPE_RETRIABLY_FAILED,
110+
OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED,
111+
];
112+
$operations = $this->operationCollectionFactory->create()
113+
->addFieldToFilter('bulk_uuid', $bulkUuid)
114+
->addFieldToFilter('status', $failureCodes)
115+
->getItems();
116+
117+
return $operations;
118+
}
119+
120+
/**
121+
* @inheritDoc
122+
*/
123+
public function getOperationsCountByBulkIdAndStatus($bulkUuid, $status)
124+
{
125+
126+
/** @var \Magento\AsynchronousOperations\Model\ResourceModel\Operation\Collection $collection */
127+
$collection = $this->operationCollectionFactory->create();
128+
129+
return $collection->addFieldToFilter('bulk_uuid', $bulkUuid)
130+
->addFieldToFilter('status', $status)
131+
->getSize();
132+
}
133+
134+
/**
135+
* @inheritDoc
136+
*/
137+
public function getBulksByUser($userId)
138+
{
139+
/** @var ResourceModel\Bulk\Collection $collection */
140+
$collection = $this->bulkCollectionFactory->create();
141+
$operationTableName = $this->resourceConnection->getTableName('magento_operation');
142+
$statusesArray = [
143+
OperationInterface::STATUS_TYPE_RETRIABLY_FAILED,
144+
OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED,
145+
BulkSummaryInterface::NOT_STARTED,
146+
OperationInterface::STATUS_TYPE_OPEN,
147+
OperationInterface::STATUS_TYPE_COMPLETE,
148+
];
149+
$select = $collection->getSelect();
150+
$select->columns(['status' => $this->calculatedStatusSql->get($operationTableName)])
151+
->order(
152+
new \Zend_Db_Expr(
153+
'FIELD(status, ' . implode(',', $statusesArray) . ')'
154+
)
155+
);
156+
$collection->addFieldToFilter('user_id', $userId)
157+
->addOrder('start_time');
158+
159+
return $collection->getItems();
160+
}
161+
162+
/**
163+
* @inheritDoc
164+
*/
165+
public function getBulkStatus($bulkUuid)
166+
{
167+
/**
168+
* Number of operations that has been processed (i.e. operations with any status but 'open')
169+
*/
170+
$allProcessedOperationsQty = (int)$this->operationCollectionFactory->create()
171+
->addFieldToFilter('bulk_uuid', $bulkUuid)
172+
->getSize();
173+
174+
if ($allProcessedOperationsQty == 0) {
175+
return BulkSummaryInterface::NOT_STARTED;
176+
}
177+
178+
/**
179+
* Total number of operations that has been scheduled within the given bulk
180+
*/
181+
$allOperationsQty = $this->getOperationCount($bulkUuid);
182+
183+
/**
184+
* Number of operations that has not been started yet (i.e. operations with status 'open')
185+
*/
186+
$allOpenOperationsQty = $allOperationsQty - $allProcessedOperationsQty;
187+
188+
/**
189+
* Number of operations that has been completed successfully
190+
*/
191+
$allCompleteOperationsQty = $this->operationCollectionFactory
192+
->create()
193+
->addFieldToFilter('bulk_uuid', $bulkUuid)
194+
->addFieldToFilter(
195+
'status',
196+
OperationInterface::STATUS_TYPE_COMPLETE
197+
)
198+
->getSize();
199+
200+
if ($allCompleteOperationsQty == $allOperationsQty) {
201+
return BulkSummaryInterface::FINISHED_SUCCESSFULLY;
202+
}
203+
204+
if ($allOpenOperationsQty > 0 && $allOpenOperationsQty !== $allOperationsQty) {
205+
return BulkSummaryInterface::IN_PROGRESS;
206+
}
207+
208+
return BulkSummaryInterface::FINISHED_WITH_FAILURE;
209+
}
210+
211+
/**
212+
* Get total number of operations that has been scheduled within the given bulk.
213+
*
214+
* @param string $bulkUuid
215+
* @return int
216+
*/
217+
private function getOperationCount($bulkUuid)
218+
{
219+
$metadata = $this->metadataPool->getMetadata(BulkSummaryInterface::class);
220+
$connection = $this->resourceConnection->getConnectionByName($metadata->getEntityConnectionName());
221+
222+
return (int)$connection->fetchOne(
223+
$connection->select()
224+
->from($metadata->getEntityTable(), 'operation_count')
225+
->where('uuid = ?', $bulkUuid)
226+
);
227+
}
228+
229+
/**
230+
* @inheritDoc
231+
*/
232+
public function getBulkDetailedStatus($bulkUuid)
233+
{
234+
$bulkSummary = $this->bulkDetailedFactory->create();
235+
236+
/** @var \Magento\AsynchronousOperations\Api\Data\DetailedBulkStatusInterface $bulk */
237+
$bulk = $this->entityManager->load($bulkSummary, $bulkUuid);
238+
239+
if ($bulk->getBulkId() === null) {
240+
throw new NoSuchEntityException(
241+
__(
242+
'Bulk uuid %bulkUuid not exist',
243+
['bulkUuid' => $bulkUuid]
244+
)
245+
);
246+
}
247+
$operations = $this->operationCollectionFactory->create()->addFieldToFilter('bulk_uuid', $bulkUuid)->getItems();
248+
$bulk->setOperationsList($operations);
249+
250+
return $bulk;
251+
}
252+
253+
/**
254+
* @inheritDoc
255+
*/
256+
public function getBulkShortStatus($bulkUuid)
257+
{
258+
$bulkSummary = $this->bulkShortFactory->create();
259+
260+
/** @var \Magento\AsynchronousOperations\Api\Data\BulkStatusInterface $bulk */
261+
$bulk = $this->entityManager->load($bulkSummary, $bulkUuid);
262+
if ($bulk->getBulkId() === null) {
263+
throw new NoSuchEntityException(
264+
__(
265+
'Bulk uuid %bulkUuid not exist',
266+
['bulkUuid' => $bulkUuid]
267+
)
268+
);
269+
}
270+
$operations = $this->operationCollectionFactory->create()->addFieldToFilter('bulk_uuid', $bulkUuid)->getItems();
271+
$bulk->setOperationsList($operations);
272+
273+
return $bulk;
274+
}
275+
}

0 commit comments

Comments
 (0)