517 lines
15 KiB
JavaScript
517 lines
15 KiB
JavaScript
define(
|
|
['underscore', 'underscore.string', 'jquery', 'pgadmin.browser', 'alertify', 'pgadmin.browser.messages'],
|
|
function(_, S, $, pgBrowser, alertify, pgMessages) {
|
|
|
|
pgBrowser.BackgroundProcessObsorver = pgBrowser.BackgroundProcessObsorver || {};
|
|
|
|
if (pgBrowser.BackgroundProcessObsorver.initialized) {
|
|
return pgBrowser.BackgroundProcessObsorver;
|
|
}
|
|
|
|
var BGProcess = function(info, notify) {
|
|
var self = this;
|
|
setTimeout(
|
|
function() {
|
|
self.initialize.apply(self, [info, notify]);
|
|
}, 1
|
|
);
|
|
};
|
|
|
|
_.extend(
|
|
BGProcess.prototype, {
|
|
initialize: function(info, notify) {
|
|
_.extend(this, {
|
|
details: false,
|
|
notify: (_.isUndefined(notify) || notify),
|
|
curr_status: null,
|
|
state: 0, // 0: NOT Started, 1: Started, 2: Finished
|
|
completed: false,
|
|
|
|
id: info['id'],
|
|
desc: null,
|
|
detailed_desc: null,
|
|
stime: null,
|
|
exit_code: null,
|
|
acknowledge: info['acknowledge'],
|
|
execution_time: null,
|
|
out: null,
|
|
err: null,
|
|
|
|
notifier: null,
|
|
container: null,
|
|
panel: null,
|
|
logs: $('<ol></ol>', {class: 'pg-bg-process-logs'})
|
|
});
|
|
|
|
if (this.notify) {
|
|
pgBrowser.Events && pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:started:' + this.id,
|
|
function(process) {
|
|
if (!process.notifier)
|
|
process.show.apply(process);
|
|
}
|
|
);
|
|
pgBrowser.Events && pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:finished:' + this.id,
|
|
function(process) {
|
|
if (!process.notifier)
|
|
process.show.apply(process);
|
|
}
|
|
)
|
|
}
|
|
var self = this;
|
|
|
|
setTimeout(
|
|
function() {
|
|
self.update.apply(self, [info]);
|
|
}, 1
|
|
);
|
|
},
|
|
|
|
url: function(type) {
|
|
var base_url = pgMessages['bgprocess.index'],
|
|
url = base_url;
|
|
|
|
switch (type) {
|
|
case 'status':
|
|
url = S('%sstatus/%s/').sprintf(base_url, this.id).value();
|
|
if (this.details) {
|
|
url = S('%s%s/%s/').sprintf(
|
|
url, (this.out && this.out.pos) || 0,
|
|
(this.err && this.err.pos) || 0
|
|
).value();
|
|
}
|
|
break;
|
|
case 'info':
|
|
case 'acknowledge':
|
|
url = S('%s%s/%s/').sprintf(base_url, type, this.id).value();
|
|
break;
|
|
}
|
|
|
|
return url;
|
|
},
|
|
|
|
update: function(data) {
|
|
var self = this,
|
|
out = [],
|
|
err = [],
|
|
idx = 0;
|
|
|
|
if ('stime' in data)
|
|
self.stime = new Date(data.stime);
|
|
|
|
if ('execution_time' in data)
|
|
self.execution_time = parseFloat(data.execution_time);
|
|
|
|
if ('desc' in data)
|
|
self.desc = data.desc;
|
|
|
|
if ('details' in data)
|
|
self.detailed_desc = data.details;
|
|
|
|
if ('exit_code' in data)
|
|
self.exit_code = data.exit_code;
|
|
|
|
if ('out' in data) {
|
|
self.out = data.out && data.out.pos;
|
|
self.completed = data.out.done;
|
|
|
|
if (data.out && data.out.lines) {
|
|
data.out.lines.sort(function(a, b) { return a[0] < b[0]; });
|
|
out = data.out.lines;
|
|
}
|
|
}
|
|
|
|
if ('err' in data) {
|
|
self.err = data.err && data.err.pos;
|
|
self.completed = (self.completed && data.err.done);
|
|
|
|
if (data.err && data.err.lines) {
|
|
data.err.lines.sort(function(a, b) { return a[0] < b[0]; });
|
|
err = data.err.lines;
|
|
}
|
|
}
|
|
|
|
var io = ie = 0;
|
|
|
|
while (io < out.length && ie < err.length &&
|
|
self.logs[0].children.length < 5120) {
|
|
if (out[io][0] < err[ie][0]){
|
|
self.logs.append(
|
|
$('<li></li>', {class: 'pg-bg-res-out'}).text(out[io++][1])
|
|
);
|
|
} else {
|
|
self.logs.append(
|
|
$('<li></li>', {class: 'pg-bg-res-err'}).text(err[ie++][1])
|
|
);
|
|
}
|
|
}
|
|
|
|
while (io < out.length && self.logs[0].children.length < 5120) {
|
|
self.logs.append(
|
|
$('<li></li>', {class: 'pg-bg-res-out'}).text(out[io++][1])
|
|
);
|
|
}
|
|
|
|
while (ie < err.length && self.logs[0].children.length < 5120) {
|
|
self.logs.append(
|
|
$('<li></li>', {class: 'pg-bg-res-err'}).text(err[ie++][1])
|
|
);
|
|
}
|
|
|
|
if (self.logs[0].children.length >= 5120) {
|
|
self.completed = true;
|
|
}
|
|
|
|
if (self.stime) {
|
|
self.curr_status = pgMessages['started'];
|
|
|
|
if (self.execution_time >= 2) {
|
|
self.curr_status = pgMessages['running'];
|
|
}
|
|
|
|
if (!_.isNull(self.exit_code)) {
|
|
if (self.exit_code == 0) {
|
|
self.curr_status = pgMessages['successfully_finished'];
|
|
} else {
|
|
self.curr_status = S(
|
|
pgMessages['failed_with_exit_code']
|
|
).sprintf(String(self.exit_code)).value();
|
|
}
|
|
}
|
|
|
|
if (self.state == 0 && self.stime) {
|
|
self.state = 1;
|
|
pgBrowser.Events && pgBrowser.Events.trigger(
|
|
'pgadmin-bgprocess:started:' + self.id, self, self
|
|
);
|
|
}
|
|
|
|
if (self.state == 1 && !_.isNull(self.exit_code)) {
|
|
self.state = 2;
|
|
pgBrowser.Events && pgBrowser.Events.trigger(
|
|
'pgadmin-bgprocess:finished:' + self.id, self, self
|
|
);
|
|
}
|
|
|
|
setTimeout(function() {self.show.apply(self)}, 10);
|
|
}
|
|
|
|
if (self.state != 2 || (self.details && !self.completed)) {
|
|
setTimeout(
|
|
function() {
|
|
self.status.apply(self);
|
|
}, 1000
|
|
);
|
|
}
|
|
},
|
|
|
|
status: function() {
|
|
var self = this;
|
|
|
|
$.ajax({
|
|
typs: 'GET',
|
|
timeout: 30000,
|
|
url: self.url('status'),
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
setTimeout(function() { self.update(res); }, 10);
|
|
},
|
|
error: function(res) {
|
|
// Try after some time
|
|
setTimeout(function() { self.update(res); }, 10000);
|
|
}
|
|
});
|
|
},
|
|
|
|
show: function() {
|
|
var self = this;
|
|
|
|
if (self.notify && !self.details) {
|
|
if (!self.notifier) {
|
|
var content = $('<div class="pg-bg-bgprocess row"></div>').append(
|
|
$('<div></div>', {
|
|
class: "h5 pg-bg-notify-header"
|
|
}).text(
|
|
self.desc
|
|
)
|
|
).append(
|
|
$('<div></div>', {class: 'pg-bg-notify-body h6' }).append(
|
|
$('<div></div>', {class: 'pg-bg-start col-xs-12' }).append(
|
|
$('<div></div>').text(self.stime.toString())
|
|
).append(
|
|
$('<div class="pg-bg-etime"></div>')
|
|
)
|
|
)
|
|
),
|
|
for_details = $('<div></div>', {
|
|
class: "col-xs-12 text-center pg-bg-click h6"
|
|
}).text(pgMessages.CLICK_FOR_DETAILED_MSG).appendTo(content),
|
|
status = $('<div></div>', {
|
|
class: "pg-bg-status col-xs-12 h5 " + ((self.exit_code === 0) ?
|
|
'bg-success': (self.exit_code == 1) ?
|
|
'bg-failed' : '')
|
|
}).appendTo(content);
|
|
|
|
self.container = content;
|
|
self.notifier = alertify.notify(
|
|
content.get(0), 'bg-bgprocess', 0, null
|
|
);
|
|
|
|
for_details.on('click', function(ev) {
|
|
ev = ev || window.event;
|
|
ev.cancelBubble = true;
|
|
ev.stopPropagation();
|
|
|
|
this.notifier.dismiss();
|
|
this.notifier = null;
|
|
|
|
this.show_detailed_view.apply(this);
|
|
}.bind(self));
|
|
|
|
// Do not close the notifier, when clicked on the container, which
|
|
// is a default behaviour.
|
|
content.on('click', function(ev) {
|
|
ev = ev || window.event;
|
|
ev.cancelBubble = true;
|
|
ev.stopPropagation();
|
|
|
|
return;
|
|
});
|
|
}
|
|
// TODO:: Formatted execution time
|
|
self.container.find('.pg-bg-etime').empty().append(
|
|
$('<span></span>', {class: 'blink'}).text(
|
|
String(self.execution_time)
|
|
)
|
|
).append(
|
|
$('<span></span>').text(' ' + pgMessages['seconds'])
|
|
);
|
|
self.container.find('.pg-bg-status').empty().append(
|
|
self.curr_status
|
|
);
|
|
} else {
|
|
self.show_detailed_view.apply(self)
|
|
}
|
|
},
|
|
|
|
show_detailed_view: function() {
|
|
var self = this,
|
|
panel = this.panel,
|
|
is_new = false;
|
|
|
|
if (!self.panel) {
|
|
is_new = true;
|
|
panel = this.panel =
|
|
pgBrowser.BackgroundProcessObsorver.create_panel();
|
|
|
|
panel.title('Process Watcher - ' + self.desc);
|
|
panel.focus();
|
|
}
|
|
|
|
var container = panel.$container,
|
|
status_class = (
|
|
(self.exit_code === 0) ?
|
|
'bg-bgprocess-success': (self.exit_code == 1) ?
|
|
'bg-bgprocess-failed' : ''
|
|
),
|
|
$logs = container.find('.bg-process-watcher'),
|
|
$header = container.find('.bg-process-details'),
|
|
$footer = container.find('.bg-process-footer');
|
|
|
|
if (is_new) {
|
|
// set logs
|
|
$logs.html(self.logs);
|
|
|
|
// set bgprocess detailed description
|
|
$header.find('.bg-detailed-desc').html(self.detailed_desc);
|
|
}
|
|
|
|
// set bgprocess start time
|
|
$header.find('.bg-process-stats .bgprocess-start-time').html(
|
|
self.stime
|
|
);
|
|
|
|
// set status
|
|
$footer.find('.bg-process-status p').removeClass().addClass(
|
|
status_class
|
|
).html(self.curr_status);
|
|
|
|
// set bgprocess execution time
|
|
$footer.find('.bg-process-exec-time p').empty().append(
|
|
$('<span></span>').text(
|
|
String(self.execution_time)
|
|
)
|
|
).append(
|
|
$('<span></span>').text(' ' + pgMessages['seconds'])
|
|
);
|
|
|
|
if (is_new) {
|
|
self.details = true;
|
|
setTimeout(
|
|
function() {
|
|
self.status.apply(self);
|
|
}, 1000
|
|
);
|
|
|
|
var resize_log_container = function($logs, $header, $footer) {
|
|
var h = $header.outerHeight() + $footer.outerHeight();
|
|
$logs.css('padding-bottom', h);
|
|
}.bind(panel, $logs, $header, $footer);
|
|
|
|
panel.on(wcDocker.EVENT.RESIZED, resize_log_container);
|
|
panel.on(wcDocker.EVENT.ATTACHED, resize_log_container);
|
|
panel.on(wcDocker.EVENT.DETACHED, resize_log_container);
|
|
|
|
resize_log_container();
|
|
|
|
panel.on(wcDocker.EVENT.CLOSED, function(process) {
|
|
process.panel = null;
|
|
|
|
process.details = false;
|
|
if (process.exit_code != null) {
|
|
process.acknowledge_server.apply(process);
|
|
}
|
|
}.bind(panel, this));
|
|
}
|
|
},
|
|
|
|
acknowledge_server: function() {
|
|
var self = this;
|
|
$.ajax({
|
|
type: 'PUT',
|
|
timeout: 30000,
|
|
url: self.url('acknowledge'),
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
return;
|
|
},
|
|
error: function(res) {
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
_.extend(
|
|
pgBrowser.BackgroundProcessObsorver, {
|
|
bgprocesses: {},
|
|
init: function() {
|
|
var self = this;
|
|
|
|
if (self.initialized) {
|
|
return;
|
|
}
|
|
self.initialized = true;
|
|
|
|
setTimeout(
|
|
function() {
|
|
self.update_process_list.apply(self);
|
|
}, 1000
|
|
);
|
|
|
|
pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:created',
|
|
function() {
|
|
setTimeout(
|
|
function() {
|
|
pgBrowser.BackgroundProcessObsorver.update_process_list();
|
|
}, 1000
|
|
);
|
|
}
|
|
)
|
|
},
|
|
|
|
update_process_list: function() {
|
|
var observer = this;
|
|
|
|
$.ajax({
|
|
typs: 'GET',
|
|
timeout: 30000,
|
|
url: pgMessages['bgprocess.list'],
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
if (!res) {
|
|
// FIXME::
|
|
// Do you think - we should call the list agains after some
|
|
// interval?
|
|
return;
|
|
}
|
|
for (idx in res) {
|
|
var process = res[idx];
|
|
if ('id' in process) {
|
|
if (!(process.id in observer.bgprocesses)) {
|
|
observer.bgprocesses[process.id] = new BGProcess(process);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
error: function(res) {
|
|
// FIXME:: What to do now?
|
|
}
|
|
});
|
|
},
|
|
|
|
create_panel: function() {
|
|
this.register_panel();
|
|
|
|
return pgBrowser.docker.addPanel(
|
|
'bg_process_watcher',
|
|
wcDocker.DOCK.FLOAT,
|
|
null, {
|
|
w: (screen.width < 700 ?
|
|
screen.width * 0.95 : screen.width * 0.5),
|
|
h: (screen.height < 500 ?
|
|
screen.height * 0.95 : screen.height * 0.5),
|
|
x: (screen.width < 700 ? '2%' : '25%'),
|
|
y: (screen.height < 500 ? '2%' : '25%')
|
|
});
|
|
},
|
|
|
|
register_panel: function() {
|
|
var w = pgBrowser.docker,
|
|
panels = w.findPanels('bg_process_watcher');
|
|
|
|
if (panels && panels.length >= 1)
|
|
return;
|
|
|
|
var p = new pgBrowser.Panel({
|
|
name: 'bg_process_watcher',
|
|
showTitle: true,
|
|
isCloseable: true,
|
|
isPrivate: true,
|
|
content: '<div class="bg-process-details col-xs-12">'+
|
|
'<p class="bg-detailed-desc"></p>'+
|
|
'<div class="bg-process-stats">'+
|
|
'<span><b>' + pgMessages['START_TIME'] + ': </b>'+
|
|
'<span class="bgprocess-start-time"></span>'+
|
|
'</span></div>'+
|
|
'</div>'+
|
|
'<div class="bg-process-watcher col-xs-12">'+
|
|
'</div>'+
|
|
'<div class="bg-process-footer col-xs-12">'+
|
|
'<div class="bg-process-status col-xs-6">'+
|
|
'<span><b>' + pgMessages['STATUS'] + ':</b></span><p></p>'+
|
|
'</div>'+
|
|
'<div class="bg-process-exec-time col-xs-6">'+
|
|
'<div class="exec-div pull-right">'+
|
|
'<span><b>' + pgMessages['EXECUTION_TIME'] + ':</b></span><p></p>'+
|
|
'</div>'+
|
|
'</div>'+
|
|
'</div>',
|
|
onCreate: function(myPanel, $container) {
|
|
$container.addClass('pg-no-overflow');
|
|
}
|
|
});
|
|
p.load(pgBrowser.docker);
|
|
}
|
|
});
|
|
|
|
return pgBrowser.BackgroundProcessObsorver;
|
|
});
|