mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
FIX: don't break the message bus when restoring a backup
This commit is contained in:
parent
2589a75c46
commit
96c23d51a2
8 changed files with 78 additions and 109 deletions
|
@ -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("/");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
56
app/assets/javascripts/admin/models/backup.js.es6
Normal file
56
app/assets/javascripts/admin/models/backup.js.es6
Normal file
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue