Skip to content

Commit d0dc031

Browse files
committed
Simplify consolidation code
1 parent d0d83c7 commit d0dc031

5 files changed

Lines changed: 167 additions & 171 deletions

File tree

src/migrations/Install.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use craft\commerce\records\CatalogPricingRule;
2323
use craft\commerce\records\InventoryLocation;
2424
use craft\commerce\records\TaxCategory;
25+
use craft\commerce\services\CatalogPricing;
2526
use craft\commerce\services\Coupons;
2627
use craft\commerce\services\Gateways;
2728
use craft\commerce\services\Stores;
@@ -136,8 +137,8 @@ public function createTables(): void
136137
$this->createTable(Table::CATALOG_PRICING_QUEUE, [
137138
'id' => $this->primaryKey(),
138139
'storeId' => $this->integer(),
139-
'purchasableIds' => $this->mediumText(),
140-
'catalogPricingRuleIds' => $this->mediumText(),
140+
'type' => $this->enum('type', [CatalogPricing::QUEUE_TYPE_PURCHASABLE, CatalogPricing::QUEUE_TYPE_RULE])->notNull(),
141+
'ids' => $this->mediumText(),
141142
'reserved' => $this->boolean()->notNull()->defaultValue(false),
142143
'dateCreated' => $this->dateTime()->notNull(),
143144
'dateUpdated' => $this->dateTime()->notNull(),
@@ -1103,7 +1104,7 @@ public function createIndexes(): void
11031104
$this->createIndex(null, Table::CATALOG_PRICING, ['purchasableId', 'storeId', 'isPromotionalPrice', 'price'], false);
11041105
$this->createIndex(null, Table::CATALOG_PRICING, ['purchasableId', 'storeId'], false);
11051106
$this->createIndex(null, Table::CATALOG_PRICING_QUEUE, 'reserved', false);
1106-
$this->createIndex(null, Table::CATALOG_PRICING_QUEUE, ['storeId', 'reserved'], false);
1107+
$this->createIndex(null, Table::CATALOG_PRICING_QUEUE, ['storeId', 'type', 'reserved'], false);
11071108
$this->createIndex(null, Table::CATALOG_PRICING_RULES, 'storeId', false);
11081109
$this->createIndex(null, Table::CATALOG_PRICING_RULES_USERS, 'catalogPricingRuleId', false);
11091110
$this->createIndex(null, Table::CATALOG_PRICING_RULES_USERS, 'userId', false);

src/migrations/m260407_000000_add_catalog_pricing_queue_table.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ public function safeUp(): bool
1919
$this->createTable(Table::CATALOG_PRICING_QUEUE, [
2020
'id' => $this->primaryKey(),
2121
'storeId' => $this->integer(),
22-
'purchasableIds' => $this->mediumText(),
23-
'catalogPricingRuleIds' => $this->mediumText(),
22+
'type' => $this->string(16)->notNull(),
23+
'ids' => $this->mediumText(),
2424
'reserved' => $this->boolean()->notNull()->defaultValue(false),
2525
'dateCreated' => $this->dateTime()->notNull(),
2626
'dateUpdated' => $this->dateTime()->notNull(),
@@ -29,8 +29,8 @@ public function safeUp(): bool
2929
}
3030

3131
$this->createIndexIfMissing(Table::CATALOG_PRICING_QUEUE, 'reserved', false);
32-
$this->createIndexIfMissing(Table::CATALOG_PRICING_QUEUE, ['storeId', 'reserved'], false);
33-
$this->addForeignKey(null, Table::CATALOG_PRICING_QUEUE, ['storeId'], Table::STORES, ['id'], 'CASCADE', 'CASCADE');
32+
$this->createIndexIfMissing(Table::CATALOG_PRICING_QUEUE, ['storeId', 'type', 'reserved'], false);
33+
$this->addForeignKeyIfMissing(Table::CATALOG_PRICING_QUEUE, ['storeId'], Table::STORES, ['id'], 'CASCADE', 'CASCADE');
3434

3535
return true;
3636
}
@@ -44,5 +44,3 @@ public function safeDown(): bool
4444
return false;
4545
}
4646
}
47-
48-

src/queue/jobs/CatalogPricing.php

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace craft\commerce\queue\jobs;
99

1010
use craft\commerce\Plugin;
11+
use craft\commerce\records\CatalogPricingQueue as CatalogPricingQueueRecord;
1112
use craft\queue\BaseJob;
1213

1314
class CatalogPricing extends BaseJob
@@ -30,17 +31,35 @@ class CatalogPricing extends BaseJob
3031
public function execute($queue): void
3132
{
3233
$catalogPricingService = Plugin::getInstance()->getCatalogPricing();
33-
$reservedRow = $catalogPricingService->reserveCatalogPricingQueueRow();
34+
$isConsolidatedJob = $this->storeId === null && $this->purchasableIds === null && $this->catalogPricingRuleIds === null;
35+
$catalogPricingRules = null;
36+
$purchasableIds = null;
37+
$reservedRowId = null;
3438

35-
if (!$reservedRow) {
36-
return;
37-
}
39+
if ($isConsolidatedJob) {
40+
// New method of processing catalog pricing via queue table: reserve a row and process based on its type and IDs
41+
$reservedRecord = $catalogPricingService->reserveCatalogPricingQueueRow();
3842

39-
$purchasableIds = $reservedRow['purchasableIds'] ?? $this->purchasableIds;
40-
$catalogPricingRuleIds = $reservedRow['catalogPricingRuleIds'] ?? $this->catalogPricingRuleIds;
41-
$storeId = $reservedRow['storeId'] ?? $this->storeId;
43+
if (!$reservedRecord) {
44+
return;
45+
}
46+
47+
$reservedRowId = $reservedRecord->id;
48+
$storeId = $reservedRecord->storeId;
49+
50+
if ($reservedRecord->type === CatalogPricingQueueRecord::TYPE_PURCHASABLE) {
51+
// Specific purchasable IDs: regenerate against all applicable rules
52+
$purchasableIds = $reservedRecord->getIds();
53+
} elseif ($reservedRecord->type === CatalogPricingQueueRecord::TYPE_RULE) {
54+
$catalogPricingRuleIds = $reservedRecord->getIds();
55+
}
56+
} else {
57+
// @TODO: remove these properties and behaviour at next breaking change
58+
$purchasableIds = $this->purchasableIds;
59+
$catalogPricingRuleIds = $this->catalogPricingRuleIds;
60+
$storeId = $this->storeId;
61+
}
4262

43-
$catalogPricingRules = null;
4463
if (!empty($catalogPricingRuleIds)) {
4564
$catalogPricingRules = Plugin::getInstance()->getCatalogPricingRules()
4665
->getAllCatalogPricingRules($storeId)
@@ -51,12 +70,12 @@ public function execute($queue): void
5170
try {
5271
$catalogPricingService->generateCatalogPrices($purchasableIds, $catalogPricingRules, queue: $queue);
5372

54-
if (!empty($reservedRow['id'])) {
55-
$catalogPricingService->deleteCatalogPricingQueueRow((int)$reservedRow['id']);
73+
if ($reservedRowId) {
74+
$catalogPricingService->deleteCatalogPricingQueueRow($reservedRowId);
5675
}
5776
} catch (\Throwable $e) {
58-
if (!empty($reservedRow['id'])) {
59-
$catalogPricingService->releaseCatalogPricingQueueRow((int)$reservedRow['id']);
77+
if ($reservedRowId) {
78+
$catalogPricingService->releaseCatalogPricingQueueRow($reservedRowId);
6079
}
6180

6281
throw $e;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
/**
3+
* @link https://craftcms.com/
4+
* @copyright Copyright (c) Pixel & Tonic, Inc.
5+
* @license https://craftcms.github.io/license/
6+
*/
7+
8+
namespace craft\commerce\records;
9+
10+
use craft\commerce\db\Table;
11+
use craft\db\ActiveRecord;
12+
use craft\helpers\Json;
13+
use yii\db\ActiveQueryInterface;
14+
15+
/**
16+
* Catalog Pricing Queue record.
17+
*
18+
* @property int $id
19+
* @property int|null $storeId
20+
* @property string $type
21+
* @property array|null $ids
22+
* @property bool $reserved
23+
* @property \DateTime $dateCreated
24+
* @property \DateTime $dateUpdated
25+
* @property string $uid
26+
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com>
27+
* @since 5.7.0
28+
*/
29+
class CatalogPricingQueue extends ActiveRecord
30+
{
31+
/**
32+
* Row type for purchasable-ID-based catalog pricing work.
33+
*/
34+
public const TYPE_PURCHASABLE = 'purchasable';
35+
36+
/**
37+
* Row type for rule-ID-based (or full-regeneration) catalog pricing work.
38+
*/
39+
public const TYPE_RULE = 'rule';
40+
41+
/**
42+
* @inheritdoc
43+
*/
44+
public static function tableName(): string
45+
{
46+
return Table::CATALOG_PRICING_QUEUE;
47+
}
48+
49+
/**
50+
* Returns the decoded IDs array from the JSON column value.
51+
*
52+
* @return array|null
53+
*/
54+
public function getIds(): ?array
55+
{
56+
$raw = $this->getAttribute('ids');
57+
58+
if ($raw === null || $raw === '') {
59+
return null;
60+
}
61+
62+
$decoded = Json::decodeIfJson($raw);
63+
64+
return is_array($decoded) ? $decoded : null;
65+
}
66+
67+
/**
68+
* Encodes the IDs array to JSON and stores it in the column.
69+
*
70+
* @param array|null $ids
71+
*/
72+
public function setIds(?array $ids): void
73+
{
74+
$this->setAttribute('ids', $ids !== null ? Json::encode($ids) : null);
75+
}
76+
77+
/**
78+
* @return ActiveQueryInterface
79+
*/
80+
public function getStore(): ActiveQueryInterface
81+
{
82+
return $this->hasOne(Store::class, ['id' => 'storeId']);
83+
}
84+
}

0 commit comments

Comments
 (0)