From 96c23d51a2f92d9e76a963b31cc02784b9020207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Thu, 27 Aug 2015 20:02:13 +0200 Subject: [PATCH] FIX: don't break the message bus when restoring a backup --- app/assets/javascripts/admin/models/backup.js | 90 ------------------- .../javascripts/admin/models/backup.js.es6 | 56 ++++++++++++ .../inject-discourse-objects.js.es6 | 10 +-- app/controllers/admin/backups_controller.rb | 11 ++- lib/backup_restore/backup_restore.rb | 4 +- lib/backup_restore/backuper.rb | 3 +- lib/backup_restore/restorer.rb | 11 +-- script/discourse | 2 +- 8 files changed, 78 insertions(+), 109 deletions(-) delete mode 100644 app/assets/javascripts/admin/models/backup.js create mode 100644 app/assets/javascripts/admin/models/backup.js.es6 diff --git a/app/assets/javascripts/admin/models/backup.js b/app/assets/javascripts/admin/models/backup.js deleted file mode 100644 index 8c11c9fe3..000000000 --- a/app/assets/javascripts/admin/models/backup.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - Data model for representing a backup - - @class Backup - @extends Discourse.Model - @namespace Discourse - @module Discourse -**/ -Discourse.Backup = Discourse.Model.extend({ - - /** - Destroys the current backup - - @method destroy - @returns {Promise} a promise that resolves when the backup has been destroyed - **/ - destroy: function() { - return Discourse.ajax("/admin/backups/" + this.get("filename"), { type: "DELETE" }); - }, - - /** - Starts the restoration of the current backup - - @method restore - @returns {Promise} a promise that resolves when the backup has started being restored - **/ - restore: function() { - return Discourse.ajax("/admin/backups/" + this.get("filename") + "/restore", { type: "POST" }); - } - -}); - -Discourse.Backup.reopenClass({ - - /** - Finds a list of backups - - @method find - @returns {Promise} a promise that resolves to the array of {Discourse.Backup} backup - **/ - find: function() { - return PreloadStore.getAndRemove("backups", function() { - return Discourse.ajax("/admin/backups.json"); - }).then(function(backups) { - return backups.map(function (backup) { return Discourse.Backup.create(backup); }); - }); - }, - - /** - Starts a backup - - @method start - @returns {Promise} a promise that resolves when the backup has started - **/ - start: function (withUploads) { - if (withUploads === undefined) { withUploads = true; } - return Discourse.ajax("/admin/backups", { type: "POST", data: { with_uploads: withUploads } }).then(function(result) { - if (!result.success) { bootbox.alert(result.message); } - }); - }, - - /** - Cancels a backup - - @method cancel - @returns {Promise} a promise that resolves when the backup has been cancelled - **/ - cancel: function() { - return Discourse.ajax("/admin/backups/cancel.json").then(function(result) { - if (!result.success) { bootbox.alert(result.message); } - }); - }, - - /** - Rollbacks the database to the previous working state - - @method rollback - @returns {Promise} a promise that resolves when the rollback is done - **/ - rollback: function() { - return Discourse.ajax("/admin/backups/rollback.json").then(function(result) { - if (!result.success) { - bootbox.alert(result.message); - } else { - // redirect to homepage (session might be lost) - window.location.pathname = Discourse.getURL("/"); - } - }); - } -}); diff --git a/app/assets/javascripts/admin/models/backup.js.es6 b/app/assets/javascripts/admin/models/backup.js.es6 new file mode 100644 index 000000000..8b4991b72 --- /dev/null +++ b/app/assets/javascripts/admin/models/backup.js.es6 @@ -0,0 +1,56 @@ +const Backup = Discourse.Model.extend({ + + destroy() { + return Discourse.ajax("/admin/backups/" + this.get("filename"), { type: "DELETE" }); + }, + + restore() { + return Discourse.ajax("/admin/backups/" + this.get("filename") + "/restore", { + type: "POST", + data: { client_id: window.MessageBus.clientId } + }); + } + +}); + +Backup.reopenClass({ + + find() { + return PreloadStore.getAndRemove("backups", () => Discourse.ajax("/admin/backups.json")) + .then(backups => backups.map(backup => Backup.create(backup))); + }, + + start(withUploads) { + if (withUploads === undefined) { withUploads = true; } + return Discourse.ajax("/admin/backups", { + type: "POST", + data: { + with_uploads: withUploads, + client_id: window.MessageBus.clientId + } + }).then(result => { + if (!result.success) { bootbox.alert(result.message); } + }); + }, + + cancel() { + return Discourse.ajax("/admin/backups/cancel.json") + .then(result => { + if (!result.success) { bootbox.alert(result.message); } + }); + }, + + rollback() { + return Discourse.ajax("/admin/backups/rollback.json") + .then(result => { + if (!result.success) { + bootbox.alert(result.message); + } else { + // redirect to homepage (session might be lost) + window.location.pathname = Discourse.getURL("/"); + } + }); + } +}); + +export default Backup; diff --git a/app/assets/javascripts/discourse/pre-initializers/inject-discourse-objects.js.es6 b/app/assets/javascripts/discourse/pre-initializers/inject-discourse-objects.js.es6 index 960277e02..5d78569d4 100644 --- a/app/assets/javascripts/discourse/pre-initializers/inject-discourse-objects.js.es6 +++ b/app/assets/javascripts/discourse/pre-initializers/inject-discourse-objects.js.es6 @@ -9,9 +9,7 @@ function inject() { name = arguments[1], singletonName = Ember.String.underscore(name).replace(/_/, '-') + ':main'; - Array.prototype.slice.call(arguments, 2).forEach(function(dest) { - app.inject(dest, name, singletonName); - }); + Array.prototype.slice.call(arguments, 2).forEach(dest => app.inject(dest, name, singletonName)); } function injectAll(app, name) { @@ -20,6 +18,7 @@ function injectAll(app, name) { export default { name: "inject-discourse-objects", + initialize(container, app) { const appEvents = AppEvents.create(); app.register('app-events:main', appEvents, { instantiate: false }); @@ -29,16 +28,13 @@ export default { app.register('store:main', Store); inject(app, 'store', 'route', 'controller'); - // Inject Discourse.Site to avoid using Discourse.Site.current() const site = Discourse.Site.current(); app.register('site:main', site, { instantiate: false }); injectAll(app, 'site'); - // Inject Discourse.SiteSettings to avoid using Discourse.SiteSettings globals app.register('site-settings:main', Discourse.SiteSettings, { instantiate: false }); injectAll(app, 'siteSettings'); - // Inject Session for transient data app.register('session:main', Session.current(), { instantiate: false }); injectAll(app, 'session'); @@ -46,7 +42,7 @@ export default { inject(app, 'currentUser', 'component', 'route', 'controller'); app.register('message-bus:main', window.MessageBus, { instantiate: false }); - inject(app, 'messageBus', 'route', 'controller', 'view', 'component'); + injectAll(app, 'messageBus'); app.register('location:discourse-location', DiscourseLocation); } diff --git a/app/controllers/admin/backups_controller.rb b/app/controllers/admin/backups_controller.rb index 83587ac3b..9ebe489fa 100644 --- a/app/controllers/admin/backups_controller.rb +++ b/app/controllers/admin/backups_controller.rb @@ -25,7 +25,8 @@ class Admin::BackupsController < Admin::AdminController def create opts = { publish_to_message_bus: true, - with_uploads: params.fetch(:with_uploads) == "true" + with_uploads: params.fetch(:with_uploads) == "true", + client_id: params[:client_id], } BackupRestore.backup!(current_user.id, opts) rescue BackupRestore::OperationRunningError @@ -70,8 +71,12 @@ class Admin::BackupsController < Admin::AdminController end def restore - filename = params.fetch(:id) - BackupRestore.restore!(current_user.id, filename, true) + opts = { + filename: params.fetch(:id), + client_id: params.fetch(:client_id), + publish_to_message_bus: true, + } + BackupRestore.restore!(current_user.id, opts) rescue BackupRestore::OperationRunningError render json: failed_json.merge(message: I18n.t("backup.operation_already_running")) else diff --git a/lib/backup_restore/backup_restore.rb b/lib/backup_restore/backup_restore.rb index c917be31b..e0f02ecb1 100644 --- a/lib/backup_restore/backup_restore.rb +++ b/lib/backup_restore/backup_restore.rb @@ -13,8 +13,8 @@ module BackupRestore start! BackupRestore::Backuper.new(user_id, opts) end - def self.restore!(user_id, filename, publish_to_message_bus=false) - start! BackupRestore::Restorer.new(user_id, filename, publish_to_message_bus) + def self.restore!(user_id, opts={}) + start! BackupRestore::Restorer.new(user_id, opts) end def self.rollback! diff --git a/lib/backup_restore/backuper.rb b/lib/backup_restore/backuper.rb index a1eff0221..ce273eb53 100644 --- a/lib/backup_restore/backuper.rb +++ b/lib/backup_restore/backuper.rb @@ -6,6 +6,7 @@ module BackupRestore def initialize(user_id, opts={}) @user_id = user_id + @client_id = opts[:client_id] @publish_to_message_bus = opts[:publish_to_message_bus] || false @with_uploads = opts[:with_uploads].nil? ? true : opts[:with_uploads] @@ -336,7 +337,7 @@ module BackupRestore def publish_log(message, timestamp) return unless @publish_to_message_bus data = { timestamp: timestamp, operation: "backup", message: message } - MessageBus.publish(BackupRestore::LOGS_CHANNEL, data, user_ids: [@user_id]) + MessageBus.publish(BackupRestore::LOGS_CHANNEL, data, user_ids: [@user_id], client_ids: [@client_id]) end def save_log(message, timestamp) diff --git a/lib/backup_restore/restorer.rb b/lib/backup_restore/restorer.rb index 2465905ee..167c45599 100644 --- a/lib/backup_restore/restorer.rb +++ b/lib/backup_restore/restorer.rb @@ -7,8 +7,11 @@ module BackupRestore attr_reader :success - def initialize(user_id, filename, publish_to_message_bus = false) - @user_id, @filename, @publish_to_message_bus = user_id, filename, publish_to_message_bus + def initialize(user_id, opts={}) + @user_id = user_id + @client_id = opts[:client_id] + @filename = opts[:filename] + @publish_to_message_bus = opts[:publish_to_message_bus] || false ensure_restore_is_enabled ensure_no_operation_is_running @@ -45,8 +48,6 @@ module BackupRestore switch_schema! - # TOFIX: MessageBus is busted... - migrate_database reconnect_database reload_site_settings @@ -354,7 +355,7 @@ module BackupRestore def publish_log(message, timestamp) return unless @publish_to_message_bus data = { timestamp: timestamp, operation: "restore", message: message } - MessageBus.publish(BackupRestore::LOGS_CHANNEL, data, user_ids: [@user_id]) + MessageBus.publish(BackupRestore::LOGS_CHANNEL, data, user_ids: [@user_id], client_ids: [@client_id]) end def save_log(message, timestamp) diff --git a/script/discourse b/script/discourse index dda1d493b..ee847f036 100755 --- a/script/discourse +++ b/script/discourse @@ -63,7 +63,7 @@ class DiscourseCLI < Thor begin puts "Starting restore: #{filename}" - restorer = BackupRestore::Restorer.new(Discourse.system_user.id, filename) + restorer = BackupRestore::Restorer.new(Discourse.system_user.id, filename: filename) restorer.run puts 'Restore done.' rescue BackupRestore::FilenameMissingError