diff --git a/CHANGELOG.md b/CHANGELOG.md index bfa661a..e528da5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,3 +72,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Changed - Updated core library version + +## 1.4.0 - 2020-12-08 + +### Added + +- Added support for remote volumes +- Added TTR to queue jobs (issue #38) +- Added time and duration to console command output + +### Changed + +- Bumped version number for parity between sync & backup plugins +- Updated readme to call-out cron requirement +- Fixed filename regex (issue #26 on craft-remote-sync) +- Moved shared utilities JS and CSS to core module +- Updated the formatting for file table (issue #10 on craft-remote-backup) \ No newline at end of file diff --git a/README.md b/README.md index 3274acb..076c615 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -Sync your database and assets across Craft environments using a remote destinations (AWS, Digital Ocean, Google Drive, Backblaze, Dropbox) +Sync your database and assets across Craft environments via a remote destinations (AWS, Digital Ocean, Google Drive, Backblaze, Dropbox). ## Overview @@ -44,9 +44,9 @@ To install the plugin, follow these instructions. ## Configuration -Remote Sync supports a number of destinations to push files to. Each provider has slightly different configuration so please follow the links below to get a short guide for configuring your preferred provider. +Remote Sync supports a number of cloud providers. Each provider has slightly different configuration so please follow the links below to get a short guide for configuring your preferred provider. -Bear in mind that you will need to additionally install the relevent SDK for your provider. +Bear in mind that you will need to additionally install the relevant SDK for your provider. - [Amazon S3](https://github.com/weareferal/craft-remote-backup/wiki/Amazon-S3) - [Backblaze B2](https://github.com/weareferal/craft-remote-backup/wiki/Backblaze-B2) @@ -54,11 +54,11 @@ Bear in mind that you will need to additionally install the relevent SDK for you - [Google Drive](https://github.com/weareferal/craft-remote-backup/wiki/Google-Drive) - [Digital Ocean Spaces](https://github.com/weareferal/craft-remote-backup/wiki/Digital-Ocean-Spaces) -In each case you will be required to configure the plugin via the Contorl Panel settings page and optional (but recommended) environment variables. +In each case you will be required to configure the plugin via the Control Panel settings page and optional (but recommended) environment variables. ## Usage -### Control Panel Utilties +### Control Panel Utilities ![Craft Remote Sync Utilities Screenshot](resources/img/utilities-screenshot.png) @@ -96,17 +96,17 @@ There are also console commands available for creating, pushing and pulling back You can optionally use Craft's built-in queue to sync files. This is useful when they are large and you don't want to have to wait on the Control Panel interface every time you backup. Instead, the files will be added to the queue and completed in the background. -You can enable this via the "Use Queue" lightswitch in the settings or via the `useQueue` setting in your config. +You can enable this via the "Use Queue" light-switch in the settings or via the `useQueue` setting in your config. #### ⚠️ CLI commands -The CLI commands ignore the queue setting. In other words, they will always run synchronously. This is by design as it's likely you will want to see the results of these operations if they are part of your crontab or deployment script. +The CLI commands ignore the queue setting. In other words, they will always run synchronously. This is by design as it's likely you will want to see the results of these operations if they are part of your crontab or deployment script. ### Emergency Backup When enabled, a local copy of both current database or volumes will be created and saved *before* pull & restoring a remote version. -This is a last resort in case you accidently pull and restore something you didn't mean to. Bear in mind that only 1 emergency backup is kept: +This is a last resort in case you accidentally pull and restore something you didn't mean to. Bear in mind that only 1 emergency backup is kept: - `storage/sync/emergency-backup.sql` (database) - `storage/sync/emergency-backup.zip` (volumes) @@ -176,6 +176,26 @@ If you are getting errors, the first thing to check is the Craft logs at `storag When are syncing volumes, it's possible that your PHP memory limit will cause the process to crash. Make sure your memory limit is > than the volume folder you are trying to backup. +### Large Files + +If you have a lot of volume files or a large database to back up, there are a number of potential issues you may face. + +#### Storage Issues + +All data from your volumes is copied to the local server before being sent to the remote destination. It is then zipped and sent to the remote destination. This means that for every 1Gb you want to backup, you need 2Gb extra space. + +#### Queue Operations Failing + +If you are backing up via the web interface and using the queue, you might notice backup operations failing (sometimes silently) + +##### TTR (Time to Reserve) + +TTR ("Time To Reserve") is the max time (in seconds) that a queue operation can take. This is a Craft setting and not a PHP setting, so it's not affected by the `max_execution` time. + +Remote Backup offers an easy way to adjust this value via the settings page, so if you are noticing issues backing-up then increase this value from the default 300 (5 minutes). + +![TTR setting](resources/img/ttr.png) + ## Support diff --git a/composer.json b/composer.json index 0c2ddab..c6b2ac2 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,7 @@ "name": "weareferal/remote-sync", "description": "Sync your database and assets across Craft environments", "type": "craft-plugin", + "version": "1.4.0", "keywords": [ "craft", "cms", @@ -22,7 +23,7 @@ ], "require": { "craftcms/cms": "^3.0.0-RC1", - "weareferal/remote-core": "^1.1.5" + "weareferal/remote-core": "1.4.0" }, "autoload": { "psr-4": { diff --git a/resources/img/ttr.png b/resources/img/ttr.png new file mode 100644 index 0000000..7079dd5 Binary files /dev/null and b/resources/img/ttr.png differ diff --git a/src/assets/RemoteSyncUtility/RemoteSyncUtilityAsset.php b/src/assets/RemoteSyncUtility/RemoteSyncUtilityAsset.php index 8f51989..dfaa695 100644 --- a/src/assets/RemoteSyncUtility/RemoteSyncUtilityAsset.php +++ b/src/assets/RemoteSyncUtility/RemoteSyncUtilityAsset.php @@ -20,10 +20,6 @@ public function init() 'js/RemoteSyncUtility.js' ]; - $this->css = [ - 'css/RemoteSyncUtility.css', - ]; - parent::init(); } } diff --git a/src/assets/RemoteSyncUtility/dist/css/RemoteSyncUtility.css b/src/assets/RemoteSyncUtility/dist/css/RemoteSyncUtility.css deleted file mode 100644 index 5f1fd8b..0000000 --- a/src/assets/RemoteSyncUtility/dist/css/RemoteSyncUtility.css +++ /dev/null @@ -1,117 +0,0 @@ -.rb-utilities { - position: relative; -} - -.rb-utilities-section { - position: relative; -} - -.rb-utilities-section:nth-child(2) { - margin-top: 25px; -} - -.rb-utilities-table { - margin-bottom: 10px; -} - -/* Hide Craft's default hover background on table rows */ -table.data.rb-utilities-table tbody tr:not(.disabled):hover th, -table.data.rb-utilities-table tbody tr:not(.disabled):hover td { - background-color: transparent; -} - -/* Hide template rows and collapsed rows */ -.rb-utilities-table tr.default-row, -.rb-utilities-table.rb-utilities-table--collapsed - tr:not(.default-row):nth-child(n + 4) { - display: none; -} - -.rb-utilities-table tbody tr td:first-child { - display: flex; - align-items: center; - padding-left: 0; -} - -/* "Latest" bubble */ -.rb-utilities-table tbody tr td:first-child span { - border: 1px solid #9aa5b1; - margin: 2px 0 0 10px; - padding: 3px 6px; - border-radius: 3px; - font-size: 11px; - line-height: 1; - color: #9aa5b1; -} - -/* Add green circle to the title */ -.rb-utilities-table tbody tr:not(.default-row) td:first-child:before { - display: block; - height: 10px; - width: 10px; - content: ""; - border-radius: 50%; - background-color: #78c678; - margin-right: 10px; -} - -/* "Show All" row */ -.rb-utilities-table tbody tr.show-all-row td { - padding-top: 0; - padding-bottom: 0; -} -.rb-utilities-table tr.show-all-row td a { - font-size: 12px; -} - -.rb-utilities-submit { - display: flex; - justify-content: flex-start; - align-items: center; - position: relative; -} - -/* Small status spinner */ -.rb-utilities-submit .utility-status { - width: 100px; - margin-left: 20px; - display: flex; - justify-content: flex-start; - align-items: center; -} - -.rb-utilities-submit .utility-status .progressbar { - width: 20%; - left: auto; - top: auto; -} - -.rb-utilities-form select { - min-width: 200px; -} - -.rb-utilities-overlay { - cursor: wait; - background-color: rgba(255, 255, 255, 0.75); - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; -} - -.rb-utilities-guard { - cursor: not-allowed; - background-color: rgba(255, 255, 255, 0.75); - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; -} diff --git a/src/assets/RemoteSyncUtility/dist/js/RemoteSyncUtility.js b/src/assets/RemoteSyncUtility/dist/js/RemoteSyncUtility.js index dd083b0..28ed435 100644 --- a/src/assets/RemoteSyncUtility/dist/js/RemoteSyncUtility.js +++ b/src/assets/RemoteSyncUtility/dist/js/RemoteSyncUtility.js @@ -1,223 +1,4 @@ (function ($) { - Craft.RemoteSyncUtility = Garnish.Base.extend({ - init: function (id) { - this.$element = $("#" + id); - - if (this.$element.length <= 0) { - return; - } - - this.$form = $("form", this.$element); - this.$table = $("table", this.$element); - this.$tbody = $("tbody", this.$table); - this.$showAllRow = $(".show-all-row", this.$tbody); - this.$submit = $("input.submit", this.$form); - this.$loadingOverlay = $(".rb-utilities-overlay", this.$element); - - this.label = this.$element.attr("data-label"); - this.labelPlural = this.$element.attr("data-label-plural"); - this.pullMessage = this.$element.attr("data-pull-message"); - this.deleteMessage = this.$element.attr("data-delete-message"); - - this.listActionUrl = this.$table.attr("data-list-action"); - this.pushActionUrl = this.$table.attr("data-push-action"); - this.pullActionUrl = this.$table.attr("data-pull-action"); - this.deleteActionUrl = this.$table.attr("data-delete-action"); - - this.csrfToken = this.$form.find('input[name="CRAFT_CSRF_TOKEN"]').val(); - - this.$form.on("submit", this.push.bind(this)); - - // Show all rows - this.$showAllRow.find("a").on( - "click", - function (e) { - this.$showAllRow.hide(); - this.$table.removeClass("rb-utilities-table--collapsed"); - e.preventDefault(); - }.bind(this) - ); - - this.list(); - }, - - clearTable: function () { - this.$tbody - .find("tr") - .filter(function (i, row) { - return !$(row).hasClass("default-row"); - }) - .remove(); - }, - - showLoading: function () { - this.$loadingOverlay.fadeIn(); - }, - - hideLoading: function () { - this.$loadingOverlay.fadeOut(); - }, - - hideTableNoResults: function () { - this.$tbody.find(".no-results-row").hide(); - }, - - showTableNoResults: function () { - this.$tbody.find(".no-results-row").show(); - }, - - hideTableErrors: function () { - this.$tbody.find(".errors-row").hide(); - }, - - showTableErrors: function () { - this.$tbody.find(".errors-row").show(); - }, - - updateTable: function (options, error) { - if (error) { - this.showTableErrors(); - return false; - } - - if (options.length <= 0) { - this.showTableNoResults(); - return false; - } - - // Backups are ordered newest to oldest ([0] = most recent) but we - // prepend them instead of append them to make it easier to style - for (var i = options.length - 1; i >= 0; i--) { - var $row = this.$tbody - .find(".template-row") - .clone() - .removeClass("template-row default-row"); - - var $td = $row.find("td:first"); - $td.text(options[i].label); - $td.attr("title", options[i].value); - $td.attr("data-filename", options[i].value); - - if (i === 0) { - $td.append($("").text("latest")); - } else { - $row.removeClass("first"); - } - - this.addListener( - $row.find(".pull-button"), - "click", - this.pull.bind(this, options[i].value) - ); - this.addListener( - $row.find(".delete-button"), - "click", - this.delete.bind(this, options[i].value) - ); - - this.$tbody.prepend($row); - } - - if (options.length > 3) { - this.$showAllRow.show(); - } - - return true; - }, - - /** - * Push a database/volume - */ - push: function (ev) { - if (ev) { - ev.preventDefault(); - } - this.post(this.pushActionUrl); - }, - - /** - * Pull a database/volume - */ - pull: function (filename, ev) { - if (ev) { - ev.preventDefault(); - } - var yes = confirm(this.pullMessage); - if (yes) { - this.post(this.pullActionUrl, { - filename: filename, - }); - } - }, - - /** - * Delete a database/volume - */ - delete: function (filename, ev) { - if (ev) { - ev.preventDefault(); - } - var yes = confirm(this.deleteMessage); - if (yes) { - this.post(this.deleteActionUrl, { - filename: filename, - }); - } - }, - - /** - * Get and list database/volumes - */ - list: function () { - this.clearTable(); - this.showLoading(); - $.get({ - url: Craft.getActionUrl(this.listActionUrl), - dataType: "json", - success: function (response) { - if (response["success"]) { - this.updateTable(response["options"]); - } else { - var message = "Error fetching files"; - if (response["error"]) { - message = response["error"]; - } - this.updateTable([], message); - Craft.cp.displayError(message); - } - }.bind(this), - complete: function () { - this.hideLoading(); - }.bind(this), - error: function (error) { - this.updateTable([], true); - Craft.cp.displayError("Error fetching files"); - }.bind(this), - }); - }, - - post: function (action, data = {}) { - var postData = Object.assign(data, { - CRAFT_CSRF_TOKEN: this.csrfToken, - }); - var url = Craft.getActionUrl(action); - this.showLoading(); - Craft.postActionRequest( - url, - postData, - function (response) { - if (response["success"]) { - window.location.reload(); - } else { - var message = "Error fetching files"; - if (response["error"]) { - message = response["error"]; - } - this.updateTable([], message); - Craft.cp.displayError(message); - } - }.bind(this) - ); - }, + Craft.RemoteSyncUtility = Craft.RemoteCoreUtility.extend({ }); })(jQuery); diff --git a/src/console/controllers/DatabaseController.php b/src/console/controllers/DatabaseController.php index 75337eb..344e04c 100644 --- a/src/console/controllers/DatabaseController.php +++ b/src/console/controllers/DatabaseController.php @@ -36,15 +36,17 @@ public function actionList() try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); $remoteFiles = RemoteSync::getInstance()->provider->listDatabases(); if (count($remoteFiles) <= 0) { $this->stdout("No remote databases" . PHP_EOL, Console::FG_YELLOW); } else { $this->stdout("Remote databases:" . PHP_EOL, Console::FG_GREEN); foreach ($remoteFiles as $remoteFile) { - $this->stdout(" " . $remoteFile->filename . PHP_EOL); + $this->stdout("- " . $remoteFile->filename . PHP_EOL); } } + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -61,9 +63,11 @@ public function actionPush() try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); $filename = RemoteSync::getInstance()->provider->pushDatabase(); $this->stdout("Pushed local database to remote destination:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -85,15 +89,17 @@ public function actionPrune() $this->stderr("Pruning disabled. Please enable via the Remote Sync control panel settings" . PHP_EOL, Console::FG_YELLOW); return ExitCode::CONFIG; } else { + $startTime = microtime(true); $filenames = $plugin->prune->pruneDatabases(); if (count($filenames) <= 0) { $this->stdout("No database files deleted" . PHP_EOL, Console::FG_YELLOW); } else { $this->stdout("Deleted database files:" . PHP_EOL, Console::FG_GREEN); foreach ($filenames as $filename) { - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); } } + $this->printTime($startTime); return ExitCode::OK; } } catch (\Exception $e) { @@ -112,9 +118,11 @@ public function actionPull($filename) try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); RemoteSync::getInstance()->provider->pullDatabase($filename); $this->stdout("Pulled and restored remote database:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -131,9 +139,11 @@ public function actionDelete($filename) try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); RemoteSync::getInstance()->provider->deleteDatabase($filename); $this->stdout("Deleted remote database:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -141,4 +151,8 @@ public function actionDelete($filename) } return ExitCode::OK; } + + protected function printTime($startTime) { + $this->stdout("Started at " . (string) date("Y-m-d H:i:s") . ". Duration " . (string) number_format(microtime(true) - $startTime, 2) . " seconds" . PHP_EOL); + } } diff --git a/src/console/controllers/VolumeController.php b/src/console/controllers/VolumeController.php index 153918d..54aee58 100644 --- a/src/console/controllers/VolumeController.php +++ b/src/console/controllers/VolumeController.php @@ -36,15 +36,17 @@ public function actionList() try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); $remoteFiles = RemoteSync::getInstance()->provider->listVolumes(); if (count($remoteFiles) <= 0) { $this->stdout("No remote volumes" . PHP_EOL, Console::FG_YELLOW); } else { $this->stdout("Remote volumes:" . PHP_EOL, Console::FG_GREEN); foreach ($remoteFiles as $remoteFile) { - $this->stdout(" " . $remoteFile->filename . PHP_EOL); + $this->stdout("- " . $remoteFile->filename . PHP_EOL); } } + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -61,13 +63,15 @@ public function actionPush() try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); $filename = RemoteSync::getInstance()->provider->pushVolumes(); if (!$filename) { $this->stdout("No remote volumes" . PHP_EOL, Console::FG_YELLOW); } else { $this->stdout("Pushed local volume to remote destination:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); } + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -89,15 +93,17 @@ public function actionPrune() $this->stderr("Pruning disabled. Please enable via the Remote Sync control panel settings" . PHP_EOL, Console::FG_YELLOW); return ExitCode::CONFIG; } else { + $startTime = microtime(true); $filenames = $plugin->prune->pruneVolumes(); if (count($filenames) <= 0) { $this->stdout("No volume files deleted" . PHP_EOL, Console::FG_YELLOW); } else { $this->stdout("Deleted volume files:" . PHP_EOL, Console::FG_GREEN); foreach ($filenames as $filename) { - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); } } + $this->printTime($startTime); return ExitCode::OK; } } catch (\Exception $e) { @@ -116,9 +122,11 @@ public function actionPull($filename) try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); RemoteSync::getInstance()->provider->pullVolume($filename); $this->stdout("Pulled and restored remote volume:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -135,9 +143,11 @@ public function actionDelete($filename) try { $this->requirePluginEnabled(); $this->requirePluginConfigured(); + $startTime = microtime(true); RemoteSync::getInstance()->provider->deleteVolume($filename); $this->stdout("Deleted remote volume:" . PHP_EOL, Console::FG_GREEN); - $this->stdout(" " . $filename . PHP_EOL); + $this->stdout("- " . $filename . PHP_EOL); + $this->printTime($startTime); } catch (\Exception $e) { Craft::$app->getErrorHandler()->logException($e); $this->stderr('Error: ' . $e->getMessage() . PHP_EOL, Console::FG_RED); @@ -145,4 +155,8 @@ public function actionDelete($filename) } return ExitCode::OK; } + + protected function printTime($startTime) { + $this->stdout("Started at " . (string) date("Y-m-d H:i:s") . ". Duration " . (string) number_format(microtime(true) - $startTime, 2) . " seconds" . PHP_EOL); + } } diff --git a/src/controllers/RemoteSyncController.php b/src/controllers/RemoteSyncController.php index 2996f6f..db6f35a 100644 --- a/src/controllers/RemoteSyncController.php +++ b/src/controllers/RemoteSyncController.php @@ -42,10 +42,13 @@ public function actionListDatabases() $this->requirePermission('remotesync'); $this->requirePluginEnabled(); $this->requirePluginConfigured(); + + $plugin = RemoteSync::getInstance(); + $settings = $plugin->getSettings(); try { $remoteFiles = RemoteSync::getInstance()->provider->listDatabases(); - $options = RemoteFile::toHTMLOptions($remoteFiles); + $options = RemoteFile::toHTMLOptions($remoteFiles, $settings->displayDateFormat); return $this->asJson([ "options" => $options, "success" => true @@ -62,10 +65,13 @@ public function actionListVolumes() $this->requirePermission('remotesync'); $this->requirePluginEnabled(); $this->requirePluginConfigured(); - + + $plugin = RemoteSync::getInstance(); + $settings = $plugin->getSettings(); + try { $remoteFiles = RemoteSync::getInstance()->provider->listVolumes(); - $options = RemoteFile::toHTMLOptions($remoteFiles); + $options = RemoteFile::toHTMLOptions($remoteFiles, $settings->displayDateFormat); return $this->asJson([ "options" => $options, "success" => true diff --git a/src/queue/DeleteDatabaseJob.php b/src/queue/DeleteDatabaseJob.php index e533c5a..948375c 100644 --- a/src/queue/DeleteDatabaseJob.php +++ b/src/queue/DeleteDatabaseJob.php @@ -2,14 +2,22 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class DeleteDatabaseJob extends BaseJob + +class DeleteDatabaseJob extends BaseJob implements RetryableJobInterface { public $filename; + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->deleteDatabase($this->filename); @@ -17,6 +25,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Delete remote database'; + return Craft::t('remote-sync', 'Delete remote database'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/DeleteVolumeJob.php b/src/queue/DeleteVolumeJob.php index f774489..9f6b4af 100644 --- a/src/queue/DeleteVolumeJob.php +++ b/src/queue/DeleteVolumeJob.php @@ -2,14 +2,22 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class DeleteVolumeJob extends BaseJob + +class DeleteVolumeJob extends BaseJob implements RetryableJobInterface { public $filename; + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->deleteVolume($this->filename); @@ -17,6 +25,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Delete remote volumes'; + return Craft::t('remote-sync', 'Delete remote volumes'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PruneDatabasesJob.php b/src/queue/PruneDatabasesJob.php index 0daa799..5135070 100644 --- a/src/queue/PruneDatabasesJob.php +++ b/src/queue/PruneDatabasesJob.php @@ -2,12 +2,20 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PruneDatabasesJob extends BaseJob + +class PruneDatabasesJob extends BaseJob implements RetryableJobInterface { + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->prune->pruneDatabases(); @@ -15,6 +23,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Prune databases'; + return Craft::t('remote-sync', 'Prune databases'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PruneVolumesJob.php b/src/queue/PruneVolumesJob.php index 76ec01e..5c70b2a 100644 --- a/src/queue/PruneVolumesJob.php +++ b/src/queue/PruneVolumesJob.php @@ -2,12 +2,20 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PruneVolumesJob extends BaseJob + +class PruneVolumesJob extends BaseJob implements RetryableJobInterface { + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->prune->pruneVolumes(); @@ -15,6 +23,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Prune volumes'; + return Craft::t('remote-sync', 'Prune volumes'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PullDatabaseJob.php b/src/queue/PullDatabaseJob.php index b723749..edf1373 100644 --- a/src/queue/PullDatabaseJob.php +++ b/src/queue/PullDatabaseJob.php @@ -2,14 +2,22 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PullDatabaseJob extends BaseJob + +class PullDatabaseJob extends BaseJob implements RetryableJobInterface { public $filename; + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->pullDatabase($this->filename); @@ -17,6 +25,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Pull and restore remote database'; + return Craft::t('remote-sync', 'Pull and restore remote database'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PullVolumeJob.php b/src/queue/PullVolumeJob.php index f293c57..34d1e58 100644 --- a/src/queue/PullVolumeJob.php +++ b/src/queue/PullVolumeJob.php @@ -2,14 +2,22 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PullVolumeJob extends BaseJob + +class PullVolumeJob extends BaseJob implements RetryableJobInterface { public $filename; + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->pullVolume($this->filename); @@ -17,6 +25,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Pull and restore remote volumes'; + return Craft::t('remote-sync', 'Pull and restore remote volumes'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PushDatabaseJob.php b/src/queue/PushDatabaseJob.php index 5adc17b..eb953bb 100644 --- a/src/queue/PushDatabaseJob.php +++ b/src/queue/PushDatabaseJob.php @@ -2,12 +2,20 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PushDatabaseJob extends BaseJob + +class PushDatabaseJob extends BaseJob implements RetryableJobInterface { + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->pushDatabase(); @@ -15,6 +23,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Push database'; + return Craft::t('remote-sync', 'Push database'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/queue/PushVolumeJob.php b/src/queue/PushVolumeJob.php index a273b71..42b5762 100644 --- a/src/queue/PushVolumeJob.php +++ b/src/queue/PushVolumeJob.php @@ -2,12 +2,20 @@ namespace weareferal\remotesync\queue; +use Craft; use craft\queue\BaseJob; +use yii\queue\RetryableJobInterface; use weareferal\remotesync\RemoteSync; -class PushVolumeJob extends BaseJob + +class PushVolumeJob extends BaseJob implements RetryableJobInterface { + public function getTtr() + { + return RemoteSync::getInstance()->getSettings()->queueTtr; + } + public function execute($queue) { RemoteSync::getInstance()->provider->pushVolumes(); @@ -15,6 +23,12 @@ public function execute($queue) protected function defaultDescription() { - return 'Push volumes'; + return Craft::t('remote-sync', 'Push volumes'); + } + + public function canRetry($attempt, $error) + { + // If true, errors aren't reported in the Craft Utilities queue manager + return true; } } diff --git a/src/templates/utilities/_includes/_remote-sync-section.html b/src/templates/utilities/_includes/_remote-sync-section.html index ef7bc82..09a206d 100644 --- a/src/templates/utilities/_includes/_remote-sync-section.html +++ b/src/templates/utilities/_includes/_remote-sync-section.html @@ -20,12 +20,12 @@

{{ "Remote " ~ labelPlural|t('remote-sync') }}

- + {{ "No " ~ labelPlural|t('remote-sync') }} - + {{ "Error Fetching " ~ labelPlural|t('remote-sync') }} diff --git a/src/utilities/RemoteSyncUtility.php b/src/utilities/RemoteSyncUtility.php index 6e13def..85b8c0d 100644 --- a/src/utilities/RemoteSyncUtility.php +++ b/src/utilities/RemoteSyncUtility.php @@ -6,6 +6,7 @@ use craft\base\Utility; use weareferal\remotesync\assets\RemoteSyncUtility\RemoteSyncUtilityAsset; +use weareferal\remotecore\assets\RemoteCoreUtility\RemoteCoreUtilityAsset; use weareferal\remotesync\RemoteSync; class RemoteSyncUtility extends Utility @@ -28,6 +29,7 @@ public static function iconPath() public static function contentHtml(): string { $view = Craft::$app->getView(); + $view->registerAssetBundle(RemoteCoreUtilityAsset::class); $view->registerAssetBundle(RemoteSyncUtilityAsset::class); $view->registerJs("new Craft.RemoteSyncUtility('rb-utilities-database')"); $view->registerJs("new Craft.RemoteSyncUtility('rb-utilities-volumes')");