From 1a821930896b6e458afa15526b80bb4cab73dc4b Mon Sep 17 00:00:00 2001 From: Nathaniel Hammond Date: Wed, 18 Dec 2024 08:08:24 +0000 Subject: [PATCH] =?UTF-8?q?Add=20`=E2=80=94throttle`=20option=20to=20cli?= =?UTF-8?q?=20syncing=20#112?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ src/console/controllers/SyncController.php | 23 ++++++++++++++++++++++ src/services/Products.php | 16 +++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b538783..a21bd45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Release Notes for Shopify +## Unreleased + +- `shopify/sync` commands now support a `--throttle` option. + ## 4.1.2 - 2024-04-15 - Fixed a PHP error that could occur when syncing products with emojis. ([#107](https://github.com/craftcms/shopify/issues/107)) diff --git a/src/console/controllers/SyncController.php b/src/console/controllers/SyncController.php index cc144e5..73487d8 100644 --- a/src/console/controllers/SyncController.php +++ b/src/console/controllers/SyncController.php @@ -24,6 +24,22 @@ class SyncController extends Controller /** @var string $defaultAction */ public $defaultAction = 'products'; + /** + * @var bool Whether to slow down API requests to avoid rate limiting. + * @since 4.2.0 + */ + public bool $throttle = false; + + /** + * @inheritdoc + */ + public function options($actionID): array + { + $options = parent::options($actionID); + $options[] = 'throttle'; + return $options; + } + /** * Sync all Shopify data. */ @@ -47,7 +63,14 @@ private function _syncProducts(): void $this->stdout('Syncing Shopify products…' . PHP_EOL . PHP_EOL, Console::FG_GREEN); // start timer $start = microtime(true); + + $originalThrottle = Plugin::getInstance()->getProducts()->throttle; + Plugin::getInstance()->getProducts()->throttle = $this->throttle; + Plugin::getInstance()->getProducts()->syncAllProducts(); + + Plugin::getInstance()->getProducts()->throttle = $originalThrottle; + // 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); diff --git a/src/services/Products.php b/src/services/Products.php index aea33ae..1248f58 100644 --- a/src/services/Products.php +++ b/src/services/Products.php @@ -55,6 +55,18 @@ class Products extends Component */ public const EVENT_BEFORE_SYNCHRONIZE_PRODUCT = 'beforeSynchronizeProduct'; + /** + * @var bool Whether to slow down API requests to avoid rate limiting. + * @since 4.2.0 + */ + public bool $throttle = false; + + /** + * @var int The number of seconds to sleep between requests when `$throttle` is enabled. + * @since 4.2.0 + */ + public int $sleepSeconds = 1; + /** * @param ShopifyProduct $product * @return void @@ -66,6 +78,10 @@ private function _updateProduct(ShopifyProduct $product): void $api = Plugin::getInstance()->getApi(); $variants = $api->getVariantsByProductId($product->id); + + if ($this->throttle) { + usleep((int) (1E6 * $this->sleepSeconds)); + } $productMetafields = $api->getMetafieldsByProductId($product->id); foreach ($variants as &$variant) {