Skip to content

Commit 24b6db7

Browse files
committed
MC-42775: Async REST API Wrong status of task in bulk actions log
1 parent 5b7b5e3 commit 24b6db7

File tree

5 files changed

+251
-5
lines changed

5 files changed

+251
-5
lines changed

app/code/Magento/AsynchronousOperations/Cron/MarkIncompleteOperationsAsFailed.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class MarkIncompleteOperationsAsFailed
2929
/**
3030
* Default error message
3131
*/
32-
private const ERROR_MESSAGE = 'Unknown error';
32+
private const ERROR_MESSAGE = 'Unknown Error';
3333

3434
/**
3535
* @var Operation

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function lock(EnvelopeInterface $envelope, string $consumerName): LockInt
9292
$connection->beginTransaction();
9393
try {
9494
$lock = $this->messageController->lock($envelope, $consumerName);
95-
$this->resource->getConnection()->update(
95+
$connection->update(
9696
$metadata->getEntityTable(),
9797
[
9898
'started_at' => $connection->formatDate($this->dateTime->gmtTimestamp())
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\AsynchronousOperations\Test\Unit\Model;
9+
10+
use Magento\AsynchronousOperations\Api\Data\OperationInterface;
11+
use Magento\AsynchronousOperations\Model\MessageControllerDecorator;
12+
use Magento\Framework\App\ResourceConnection;
13+
use Magento\Framework\DB\Adapter\AdapterInterface;
14+
use Magento\Framework\EntityManager\EntityMetadataInterface;
15+
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Framework\MessageQueue\EnvelopeInterface;
17+
use Magento\Framework\MessageQueue\LockInterface;
18+
use Magento\Framework\MessageQueue\MessageController;
19+
use Magento\Framework\MessageQueue\MessageEncoder;
20+
use Magento\Framework\MessageQueue\MessageValidator;
21+
use Magento\Framework\Stdlib\DateTime\DateTime;
22+
use Monolog\Test\TestCase;
23+
use PHPUnit\Framework\MockObject\MockObject;
24+
25+
class MessageControllerDecoratorTest extends TestCase
26+
{
27+
/**
28+
* @var MessageControllerDecorator
29+
*/
30+
private $model;
31+
32+
/**
33+
* @var MessageController|MockObject
34+
*/
35+
private $messageController;
36+
37+
/**
38+
* @var MetadataPool|MockObject
39+
*/
40+
private $metadataPool;
41+
42+
/**
43+
* @var ResourceConnection|MockObject
44+
*/
45+
private $resource;
46+
47+
/**
48+
* @var MessageEncoder|MockObject
49+
*/
50+
private $messageEncoder;
51+
52+
/**
53+
* @var DateTime|MockObject
54+
*/
55+
private $dateTime;
56+
57+
/**
58+
* @inheritdoc
59+
*/
60+
protected function setUp(): void
61+
{
62+
parent::setUp();
63+
$this->resource = $this->createMock(ResourceConnection::class);
64+
$this->messageController = $this->createMock(MessageController::class);
65+
$messageValidator = $this->createMock(MessageValidator::class);
66+
$this->messageEncoder = $this->createMock(MessageEncoder::class);
67+
$this->metadataPool = $this->createMock(MetadataPool::class);
68+
$this->dateTime = $this->createMock(DateTime::class);
69+
$this->model = new MessageControllerDecorator(
70+
$this->resource,
71+
$this->messageController,
72+
$messageValidator,
73+
$this->messageEncoder,
74+
$this->metadataPool,
75+
$this->dateTime
76+
);
77+
}
78+
79+
public function testLock(): void
80+
{
81+
$bUuid = uniqid();
82+
$operationId = 0;
83+
$operationTableName = 'table_1';
84+
$connectionName = 'connection_1';
85+
$timestamp = 1631104794;
86+
$date = '2021-09-08 12:39:54';
87+
$this->dateTime->method('gmtTimestamp')
88+
->willReturn($timestamp);
89+
$metadata = $this->createMock(EntityMetadataInterface::class);
90+
$metadata->method('getEntityConnectionName')
91+
->willReturn($connectionName);
92+
$metadata->method('getEntityTable')
93+
->willReturn($operationTableName);
94+
$this->metadataPool->method('getMetadata')
95+
->with(OperationInterface::class)
96+
->willReturn($metadata);
97+
$connection = $this->createMock(AdapterInterface::class);
98+
$this->resource->method('getConnection')
99+
->with($connectionName)
100+
->willReturn($connection);
101+
$operation = $this->createMock(OperationInterface::class);
102+
$operation->method('getId')
103+
->willReturn($operationId);
104+
$operation->method('getBulkUuid')
105+
->willReturn($bUuid);
106+
$this->messageEncoder->method('decode')
107+
->willReturn($operation);
108+
$envelope = $this->createMock(EnvelopeInterface::class);
109+
$lock = $this->createMock(LockInterface::class);
110+
$consumerName = 'consumer_1';
111+
$this->messageController->expects($this->once())
112+
->method('lock')
113+
->with($envelope, $consumerName)
114+
->willReturn($lock);
115+
$connection->expects($this->once())
116+
->method('formatDate')
117+
->with($timestamp)
118+
->willReturn($date);
119+
$connection->expects($this->once())
120+
->method('update')
121+
->with(
122+
$operationTableName,
123+
[
124+
'started_at' => $date
125+
],
126+
[
127+
'bulk_uuid = ?' => $bUuid,
128+
'operation_key = ?' => $operationId
129+
]
130+
);
131+
$this->assertSame($lock, $this->model->lock($envelope, $consumerName));
132+
}
133+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace integration\testsuite\Magento\AsynchronousOperations\Cron;
9+
10+
use Magento\AsynchronousOperations\Api\Data\OperationInterface;
11+
use Magento\AsynchronousOperations\Api\Data\OperationInterfaceFactory;
12+
use Magento\AsynchronousOperations\Api\SaveMultipleOperationsInterface;
13+
use Magento\AsynchronousOperations\Cron\MarkIncompleteOperationsAsFailed;
14+
use Magento\AsynchronousOperations\Model\ResourceModel\Operation\Collection;
15+
use Magento\AsynchronousOperations\Model\ResourceModel\Operation\CollectionFactory;
16+
use Magento\Framework\App\ResourceConnection;
17+
use Magento\Framework\Bulk\BulkManagementInterface;
18+
use Magento\Framework\Serialize\Serializer\Json;
19+
use Magento\TestFramework\Helper\Bootstrap;
20+
use PHPUnit\Framework\TestCase;
21+
22+
/**
23+
* Test for MarkIncompleteOperationsAsFailed
24+
*
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26+
*/
27+
class MarkIncompleteOperationsAsFailedTest extends TestCase
28+
{
29+
/**
30+
* @var MarkIncompleteOperationsAsFailed
31+
*/
32+
private $model;
33+
34+
/**
35+
* @inheritdoc
36+
*/
37+
protected function setUp(): void
38+
{
39+
parent::setUp();
40+
$objectManager = Bootstrap::getObjectManager();
41+
$this->model = $objectManager->create(MarkIncompleteOperationsAsFailed::class);
42+
}
43+
44+
/**
45+
* @magentoDbIsolation enabled
46+
*/
47+
public function testExecute(): void
48+
{
49+
$objectManager = Bootstrap::getObjectManager();
50+
$jsonSerializer = $objectManager->get(Json::class);
51+
$resource = $objectManager->get(ResourceConnection::class);
52+
$topicName = 'topic_name_1';
53+
$buuid = uniqid('bulk-');
54+
$startedAt = $resource->getConnection()->formatDate(new \DateTime('-14 hours', new \DateTimeZone('UTC')));
55+
$operationsData = [
56+
[
57+
OperationInterface::ID => 0,
58+
OperationInterface::STATUS => OperationInterface::STATUS_TYPE_COMPLETE,
59+
'started_at' => $startedAt,
60+
],
61+
[
62+
OperationInterface::ID => 1,
63+
OperationInterface::STATUS => OperationInterface::STATUS_TYPE_OPEN,
64+
'started_at' => $startedAt,
65+
],
66+
[
67+
OperationInterface::ID => 2,
68+
OperationInterface::STATUS => OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED,
69+
'started_at' => $startedAt,
70+
],
71+
[
72+
OperationInterface::ID => 3,
73+
OperationInterface::STATUS => OperationInterface::STATUS_TYPE_OPEN,
74+
'started_at' => null,
75+
]
76+
];
77+
$operationFactory = $objectManager->get(OperationInterfaceFactory::class);
78+
$operations = [];
79+
foreach ($operationsData as $data) {
80+
$data += [
81+
OperationInterface::BULK_ID => $buuid,
82+
OperationInterface::TOPIC_NAME => $topicName,
83+
OperationInterface::SERIALIZED_DATA => $jsonSerializer->serialize([]),
84+
];
85+
$operations[] = $operationFactory->create(['data' => $data]);
86+
}
87+
$bulkManagement = $objectManager->get(BulkManagementInterface::class);
88+
$saveMultipleOperations = $objectManager->get(SaveMultipleOperationsInterface::class);
89+
$bulkManagement->scheduleBulk($buuid, [], 'test bulk');
90+
$saveMultipleOperations->execute($operations);
91+
92+
$this->model->execute();
93+
94+
$operationCollectionFactory = $objectManager->get(CollectionFactory::class);
95+
/** @var Collection $collection */
96+
$collection = $operationCollectionFactory->create();
97+
$collection->addFieldToFilter(
98+
OperationInterface::BULK_ID,
99+
['eq' => $buuid]
100+
);
101+
$collection->addFieldToFilter(
102+
OperationInterface::STATUS,
103+
['eq' => OperationInterface::STATUS_TYPE_RETRIABLY_FAILED]
104+
);
105+
$this->assertEquals(1, $collection->count());
106+
$operation = $collection->getFirstItem();
107+
$this->assertEquals(1, $operation->getId());
108+
$this->assertEquals(0, $operation->getErrorCode());
109+
$this->assertEquals('Unknown Error', $operation->getResultMessage());
110+
}
111+
}

dev/tests/integration/testsuite/Magento/AsynchronousOperations/Model/MassConsumerEnvelopeCallbackTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
/**
2828
* Test for MassConsumerEnvelopeCallback
29+
*
30+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2931
*/
3032
class MassConsumerEnvelopeCallbackTest extends TestCase
3133
{
@@ -67,7 +69,7 @@ class MassConsumerEnvelopeCallbackTest extends TestCase
6769
/**
6870
* @var CollectionFactory
6971
*/
70-
private $operationCollection;
72+
private $operationCollectionFactory;
7173

7274
/**
7375
* @inheritdoc
@@ -81,7 +83,7 @@ protected function setUp(): void
8183
$this->messageEncoder = $objectManager->get(MessageEncoder::class);
8284
$this->operationRepository = $objectManager->get(OperationRepositoryInterface::class);
8385
$operationProcessor = $this->createMock(OperationProcessor::class);
84-
$this->operationCollection = $objectManager->get(CollectionFactory::class);
86+
$this->operationCollectionFactory = $objectManager->get(CollectionFactory::class);
8587
$this->bulkManagement = $objectManager->get(BulkManagementInterface::class);
8688
$this->saveMultipleOperations = $objectManager->get(SaveMultipleOperationsInterface::class);
8789
$operationProcessorFactory = $this->createMock(OperationProcessorFactory::class);
@@ -134,7 +136,7 @@ public function testMessageLock(): void
134136
$this->model->execute($envelope);
135137

136138
/** @var Collection $collection */
137-
$collection = $this->operationCollection->create();
139+
$collection = $this->operationCollectionFactory->create();
138140
$collection->addFieldToFilter(OperationInterface::BULK_ID, ['eq' => $buuid]);
139141
$this->assertEquals(1, $collection->count());
140142
$operation = $collection->getFirstItem();

0 commit comments

Comments
 (0)