Skip to content

Commit

Permalink
Merge pull request #85 from craftcms/feature/user-package-retries
Browse files Browse the repository at this point in the history
Use the built-in retry behavior in the API package
  • Loading branch information
lukeholder authored Nov 2, 2023
2 parents 828e0d7 + 49ac028 commit 2d2da26
Show file tree
Hide file tree
Showing 11 changed files with 25 additions and 165 deletions.
11 changes: 3 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@

## 4.0.0 - WIP
- Shopify now requires `shopify/shopify-api` 5.2.0 or later.
- Shopify now requires custom apps to be created with event version set to `2023-10`.

## Unreleased

- Added an `async` flag to the `craft/shopify/sync` command.
- Added an `async` param to the sync utility.
- Shopify now the related custom app to be created with event version set to `2023-10`.
- Syncing meta fields is no longer performed in a job.
- Deprecated the `craft\shopify\jobs\UpdateProductMetadata` job.
- Fixed a bug where the template routing setting would not save.
- Added `craft\shopify\helpers\Api`.
- Added `craft\shopify\jobs\UpdateProductVariants`.

## 3.2.0 - 2023-06-12

Expand Down
25 changes: 7 additions & 18 deletions src/console/controllers/SyncController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use craft\console\Controller;
use craft\helpers\Console;
use craft\shopify\elements\Product;
use craft\shopify\Plugin;
use yii\console\ExitCode;

Expand All @@ -23,22 +24,6 @@ class SyncController extends Controller
/** @var string $defaultAction */
public $defaultAction = 'products';

/**
* @var bool Whether to sync product and other associated data in the queue.
* @since 3.3.0
*/
public bool $async = true;

/**
* @inheritdoc
*/
public function options($actionID): array
{
$options = parent::options($actionID);
$options[] = 'async';
return $options;
}

/**
* Sync all Shopify data.
*/
Expand All @@ -60,7 +45,11 @@ public function actionProducts(): int
private function _syncProducts(): void
{
$this->stdout('Syncing Shopify products…' . PHP_EOL . PHP_EOL, Console::FG_GREEN);
Plugin::getInstance()->getProducts()->syncAllProducts($this->async);
$this->stdout('Finished' . PHP_EOL . PHP_EOL, Console::FG_GREEN);
// start timer
$start = microtime(true);
Plugin::getInstance()->getProducts()->syncAllProducts();
// end timer
$time = microtime(true) - $start;
$this->stdout('Finished syncing ' . Product::find()->count() . ' product(s) in ' . round($time, 2) . 's' . PHP_EOL . PHP_EOL, Console::FG_GREEN);
}
}
4 changes: 1 addition & 3 deletions src/controllers/ProductsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ public function actionProductIndex(): Response
*/
public function actionSync(): Response
{
$async = (bool)Craft::$app->getRequest()->getParam('async', false);

Plugin::getInstance()->getProducts()->syncAllProducts($async);
Plugin::getInstance()->getProducts()->syncAllProducts();
return $this->asSuccess(Craft::t('shopify', 'Products successfully synced'));
}

Expand Down
31 changes: 0 additions & 31 deletions src/helpers/Api.php

This file was deleted.

4 changes: 2 additions & 2 deletions src/jobs/UpdateProductMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

use craft\queue\BaseJob;
use craft\shopify\elements\Product;
use craft\shopify\helpers\Api as ApiHelper;
use craft\shopify\helpers\Metafields as MetafieldsHelper;
use craft\shopify\Plugin;
use craft\shopify\records\ProductData as ProductDataRecord;

/**
* Updates the metadata for a Shopify product.
*
* @deprecated 4.0.0 No longer used internally due to the use of `Retry-After` headers in the Shopify API.
*/
class UpdateProductMetadata extends BaseJob
{
Expand All @@ -31,7 +32,6 @@ public function execute($queue): void
$productData = ProductDataRecord::find()->where(['shopifyId' => $this->shopifyProductId])->one();
$productData->metaFields = $metaFields;
$productData->save();
ApiHelper::rateLimit(); // Avoid rate limiting
}
}

Expand Down
47 changes: 0 additions & 47 deletions src/jobs/UpdateProductVariants.php

This file was deleted.

15 changes: 0 additions & 15 deletions src/models/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,10 @@ class Settings extends Model
public string $template = '';
private mixed $_productFieldLayout;

/**
* @var bool Whether to rate limit requests to Shopify
* @since 3.3.0
*/
public bool $rateLimitRequests = true;

/**
* @var int The number of seconds to wait between requests
* @since 3.3.0
*/
public int $rateLimitSeconds = 1;

public function rules(): array
{
return [
[['apiSecretKey', 'apiKey', 'accessToken', 'hostName'], 'required'],
[['rateLimitSeconds', 'rateLimitRequests'], 'safe'],
];
}

Expand All @@ -60,8 +47,6 @@ public function attributeLabels(): array
'hostName' => Craft::t('shopify', 'Shopify Host Name'),
'uriFormat' => Craft::t('shopify', 'Product URI format'),
'template' => Craft::t('shopify', 'Product Template'),
'rateLimitRequests' => Craft::t('shopify', 'Rate Limit Requests'),
'rateLimitSeconds' => Craft::t('shopify', 'Rate Limit Seconds'),
];
}

Expand Down
10 changes: 6 additions & 4 deletions src/services/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use craft\base\Component;
use craft\helpers\App;
use craft\log\MonologTarget;
use craft\shopify\helpers\Api as ApiHelper;
use craft\shopify\Plugin;
use Shopify\Auth\FileSessionStorage;
use Shopify\Auth\Session;
Expand Down Expand Up @@ -92,15 +91,19 @@ public function getProductIdByInventoryItemId($id): ?int
* Retrieves "metafields" for the provided Shopify product ID.
*
* @param int $id Shopify Product ID
* @return ShopifyMetafield[]
*/
public function getMetafieldsByProductId(int $id): array
{
return $this->getAll(ShopifyMetafield::class, [
/** @var ShopifyMetafield[] $metafields */
$metafields = $this->getAll(ShopifyMetafield::class, [
'metafield' => [
'owner_id' => $id,
'owner_resource' => 'product',
],
]);

return $metafields;
}

/**
Expand Down Expand Up @@ -147,7 +150,6 @@ public function getAll(string $type, array $params = []): array
[],
$type::$NEXT_PAGE_QUERY ?: $params,
));
ApiHelper::rateLimit(); // Avoid rate limiting
} while ($type::$NEXT_PAGE_QUERY);

return $resources;
Expand Down Expand Up @@ -196,7 +198,7 @@ public function getSession(): ?Session
sessionStorage: new FileSessionStorage(Craft::$app->getPath()->getStoragePath() . DIRECTORY_SEPARATOR . 'shopify_api_sessions'),
apiVersion: self::SHOPIFY_API_VERSION,
isEmbeddedApp: false,
logger: $webLogTarget->getLogger()
logger: $webLogTarget->getLogger(),
);

$hostName = App::parseEnv($pluginSettings->hostName);
Expand Down
32 changes: 6 additions & 26 deletions src/services/Products.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
use craft\shopify\elements\Product;
use craft\shopify\elements\Product as ProductElement;
use craft\shopify\events\ShopifyProductSyncEvent;
use craft\shopify\helpers\Api as ApiHelper;
use craft\shopify\helpers\Metafields as MetafieldsHelper;
use craft\shopify\jobs\UpdateProductMetadata;
use craft\shopify\jobs\UpdateProductVariants;
use craft\shopify\Plugin;
use craft\shopify\records\ProductData as ProductDataRecord;
use Shopify\Rest\Admin2023_10\Metafield as ShopifyMetafield;
Expand Down Expand Up @@ -61,32 +58,15 @@ class Products extends Component
* @throws \Throwable
* @throws \yii\base\InvalidConfigException
*/
public function syncAllProducts(bool $asynchronous = true): void
public function syncAllProducts(): void
{
$api = Plugin::getInstance()->getApi();
$products = $api->getAllProducts();

foreach ($products as $product) {
if ($asynchronous) {
$this->createOrUpdateProduct($product);
Craft::$app->getQueue()->push(new UpdateProductMetadata([
'description' => Craft::t('shopify', 'Updating product metafields for “{title}”', [
'title' => $product->title,
]),
'shopifyProductId' => $product->id,
]));
Craft::$app->getQueue()->push(new UpdateProductVariants([
'description' => Craft::t('shopify', 'Updating product variants for “{title}”', [
'title' => $product->title,
]),
'shopifyProductId' => $product->id,
]));
} else {
$metaFields = $api->getMetafieldsByProductId($product->id);
ApiHelper::rateLimit();
$variants = $api->getVariantsByProductId($product->id);
$this->createOrUpdateProduct($product, $metaFields, $variants);
}
$variants = $api->getVariantsByProductId($product->id);
$metafields = $api->getMetafieldsByProductId($product->id);
$this->createOrUpdateProduct($product, $metafields, $variants);
}

// Remove any products that are no longer in Shopify just in case.
Expand Down Expand Up @@ -126,7 +106,8 @@ public function syncProductByInventoryItemId($id): void
if ($productId = $api->getProductIdByInventoryItemId($id)) {
$product = $api->getProductByShopifyId($productId);
$metaFields = $api->getMetafieldsByProductId($product->id);
$this->createOrUpdateProduct($product, $metaFields);
$variants = $api->getVariantsByProductId($product->id);
$this->createOrUpdateProduct($product, $metaFields, $variants);
}
}

Expand Down Expand Up @@ -161,7 +142,6 @@ public function createOrUpdateProduct(ShopifyProduct $product, array $metafields
'updatedAt' => $product->updated_at,
'variants' => $variants ?? $product->variants,
'vendor' => $product->vendor,
// This one is unusual, because we’re merging two different Shopify API resources:
'metaFields' => $metaFields,
];

Expand Down
9 changes: 0 additions & 9 deletions src/templates/utilities/_sync.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@
{{ actionInput('') }}
{{ csrfInput() }}

{{ forms.lightswitchField({
label: "Use queue for syncing related objects like meta fields."|t('shopify'),
warning: 'If disabled timeouts may occur, or API rate limits may be hit.'|t('commerce'),
id: 'async',
name: 'async',
value: 1,
on: true
}) }}

<a class="btn submit formsubmit" data-icon="refresh"
data-action="shopify/products/sync"
data-confirm="{{ 'Are you sure you want run a complete sync of all products?'|t('shopify') }}">
Expand Down
2 changes: 0 additions & 2 deletions src/translations/en/shopify.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
return [
'Product Template' => 'Product Template',
'Product URI format' => 'Product URI format',
'Rate Limit Requests' => 'Rate Limit Requests',
'Rate Limit Seconds' => 'Rate Limit Seconds',
'Shopify API Key' => 'Shopify API Key',
'Shopify API Secret Key' => 'Shopify API Secret Key',
'Shopify Access Token' => 'Shopify Access Token',
Expand Down

0 comments on commit 2d2da26

Please sign in to comment.