mirror of
https://github.com/apankrat/nullboard.git
synced 2025-08-09 14:46:57 +02:00
serialize requests in BackupStorage
This commit is contained in:
438
nullboard.html
438
nullboard.html
@@ -1696,10 +1696,13 @@
|
|||||||
this.listWidth = null; // list-width
|
this.listWidth = null; // list-width
|
||||||
this.theme = null; // default or 'dark'
|
this.theme = null; // default or 'dark'
|
||||||
|
|
||||||
this.backups = [ ]; // [ { type, id, enabled, conf } ];
|
|
||||||
this.nextBackupId = 1;
|
|
||||||
|
|
||||||
this.board = null; // active board
|
this.board = null; // active board
|
||||||
|
|
||||||
|
this.backups =
|
||||||
|
{
|
||||||
|
agents : [ ], // [ { type, id, enabled, conf } ];
|
||||||
|
nextId : 1
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function BoardMeta()
|
function BoardMeta()
|
||||||
@@ -1708,7 +1711,7 @@
|
|||||||
this.current = 1; // revision
|
this.current = 1; // revision
|
||||||
this.ui_spot = 0; // 0 = not set
|
this.ui_spot = 0; // 0 = not set
|
||||||
this.history = [ ]; // revision IDs
|
this.history = [ ]; // revision IDs
|
||||||
this.backups = [ ]; // backup agents IDs with which this board is stored
|
this.backups = [ ]; // agents that this board is backed up with
|
||||||
}
|
}
|
||||||
|
|
||||||
class Storage
|
class Storage
|
||||||
@@ -1720,9 +1723,11 @@
|
|||||||
this.conf = new AppConfig();
|
this.conf = new AppConfig();
|
||||||
this.boardIndex = new Map();
|
this.boardIndex = new Map();
|
||||||
|
|
||||||
this.backups = []; // BackupStorage
|
this.backups =
|
||||||
this.backupStatus = ''; // '', 'ok', 'busy', 'failed'
|
{
|
||||||
this.backupCb = null;
|
status : '', // '', 'ok', 'busy', 'failed'
|
||||||
|
agents : [ ], // BackupStorage instances
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
open()
|
open()
|
||||||
@@ -1740,9 +1745,12 @@
|
|||||||
return this.conf;
|
return this.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
setVerLast(ver)
|
setVerLast()
|
||||||
{
|
{
|
||||||
this.conf.verLast = ver || NB.codeVersion;
|
if (this.conf.verLast == NB.codeVersion)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
this.conf.verLast = NB.codeVersion;
|
||||||
return this.saveConfig();
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1754,6 +1762,8 @@
|
|||||||
|
|
||||||
setActiveBoard(board_id)
|
setActiveBoard(board_id)
|
||||||
{
|
{
|
||||||
|
console.log('setActiveBoard [' + this.conf.board + '] -> [' + board_id + ']');
|
||||||
|
|
||||||
var meta = board_id ? this.boardIndex.get(board_id) : true;
|
var meta = board_id ? this.boardIndex.get(board_id) : true;
|
||||||
|
|
||||||
if (! meta)
|
if (! meta)
|
||||||
@@ -1944,7 +1954,7 @@
|
|||||||
this.delItem('board.' + board_id + '.meta');
|
this.delItem('board.' + board_id + '.meta');
|
||||||
this.boardIndex.delete(board_id);
|
this.boardIndex.delete(board_id);
|
||||||
|
|
||||||
this.backups.forEach(function(store){
|
this.backups.agents.forEach(function(store){
|
||||||
store.nukeBoard(board_id);
|
store.nukeBoard(board_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2042,22 +2052,26 @@
|
|||||||
conf.verSeen = 20200220; // 20200429;
|
conf.verSeen = 20200220; // 20200429;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.backups.length != 2 ||
|
var agents = conf.backups.agents;
|
||||||
conf.backups[0].type != simp || conf.backups[0].conf.base != 'http://127.0.0.1:10001' ||
|
|
||||||
conf.backups[1].type != simp)
|
|
||||||
{
|
|
||||||
console.log('Unexpected backup config, will re-initialize.', conf.backups);
|
|
||||||
|
|
||||||
conf.backups.push({
|
if (agents.length != 2 ||
|
||||||
|
agents[0].type != simp || agents[0].conf.base != 'http://127.0.0.1:10001' ||
|
||||||
|
agents[1].type != simp)
|
||||||
|
{
|
||||||
|
console.log('Unexpected backup config, will re-initialize.', agents);
|
||||||
|
|
||||||
|
conf.backups.agents = [];
|
||||||
|
|
||||||
|
conf.backups.agents.push({
|
||||||
type: simp,
|
type: simp,
|
||||||
id: simp + '-' + (conf.nextBackupId++),
|
id: simp + '-' + (conf.backups.nextId++),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
conf: { base: 'http://127.0.0.1:10001', auth: '' }
|
conf: { base: 'http://127.0.0.1:10001', auth: '' }
|
||||||
})
|
})
|
||||||
|
|
||||||
conf.backups.push({
|
conf.backups.agents.push({
|
||||||
type: simp,
|
type: simp,
|
||||||
id: simp + '-' + (conf.nextBackupId++),
|
id: simp + '-' + (conf.backups.nextId++),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
conf: { base: '', auth: '' }
|
conf: { base: '', auth: '' }
|
||||||
})
|
})
|
||||||
@@ -2069,20 +2083,18 @@
|
|||||||
/*
|
/*
|
||||||
* backups
|
* backups
|
||||||
*/
|
*/
|
||||||
initBackups(backupStatusCb)
|
initBackups(onBackupStatus)
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
var pending = 0;
|
var pending = 0;
|
||||||
var success = true;
|
var success = true;
|
||||||
var store_id = 1;
|
var store_id = 1;
|
||||||
|
|
||||||
NB.storage.backupCb = backupStatusCb;
|
self.backups.agents = [];
|
||||||
|
|
||||||
this.backups = [];
|
onBackupStatus(null);
|
||||||
|
|
||||||
self.setBackupStatus('');
|
this.conf.backups.agents.forEach(function(b){
|
||||||
|
|
||||||
this.conf.backups.forEach(function(b){
|
|
||||||
|
|
||||||
var T = NB.backupTypes.get(b.type);
|
var T = NB.backupTypes.get(b.type);
|
||||||
if (! T)
|
if (! T)
|
||||||
@@ -2094,59 +2106,40 @@
|
|||||||
if (! b.enabled)
|
if (! b.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var store = new T(b.id, b.conf);
|
var agent = new T(b.id, b.conf, onBackupStatus);
|
||||||
self.backups.push(store);
|
self.backups.agents.push(agent);
|
||||||
|
|
||||||
console.log( `Added backup storage - type '${store.type}', id '${store.id}'` );
|
console.log( `Added backup agent - type '${agent.type}', id '${agent.id}'` );
|
||||||
|
|
||||||
self.setBackupStatus('busy');
|
agent.checkStatus(null); // will need just onBackupStatus() callbacks
|
||||||
|
|
||||||
pending++;
|
|
||||||
store.checkStatus(function(ok, xhr){
|
|
||||||
console.log( `Backup storage '${store.id}' is ${ok ? 'ready' : 'NOT ready'} ` );
|
|
||||||
|
|
||||||
store.last = { ok: ok, text: xhr.responseText, code: xhr.status };
|
|
||||||
success &= ok;
|
|
||||||
|
|
||||||
if (--pending)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.setBackupStatus(success ? 'ok' : 'failed');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
backupBoard(board_id, board, meta)
|
backupBoard(board_id, board, meta)
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
var pending = 0;
|
|
||||||
var success = true;
|
|
||||||
|
|
||||||
meta.backups = [];
|
if (! this.backups.agents.length)
|
||||||
|
|
||||||
if (! this.backups.length)
|
|
||||||
{
|
{
|
||||||
this.setBackupStatus('');
|
meta.backups = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setBackupStatus('busy');
|
meta.backups = [];
|
||||||
|
|
||||||
this.backups.forEach(function(store){
|
console.log( `Backing up ${board_id}...` );
|
||||||
pending++;
|
|
||||||
store.saveBoard(board_id, board, meta, function(ok){
|
this.backups.agents.forEach(function(agent){
|
||||||
|
|
||||||
|
agent.saveBoard(board_id, board, meta, function(){
|
||||||
|
|
||||||
var what = 'Backup of ' + board_id + (board ? '' : ' (meta)');
|
var what = 'Backup of ' + board_id + (board ? '' : ' (meta)');
|
||||||
console.log( `${what} to '${store.id}' -> ${ok ? 'ok' : 'failed'}` );
|
console.log( `${what} to '${agent.id}' -> ${agent.status}` );
|
||||||
|
|
||||||
if (ok) meta.backups.push(store.id);
|
if (agent.status == 'ready')
|
||||||
else success = false;
|
meta.backups.push(agent.id);
|
||||||
|
|
||||||
if (--pending)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.setJson('board.' + board_id + '.meta', meta);
|
self.setJson('board.' + board_id + '.meta', meta);
|
||||||
self.setBackupStatus(success ? 'ok' : 'failed');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2154,34 +2147,14 @@
|
|||||||
backupConfig()
|
backupConfig()
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
var pending = 0;
|
|
||||||
var success = true;
|
|
||||||
|
|
||||||
if (! this.backups.length)
|
if (! this.backups.agents.length)
|
||||||
{
|
|
||||||
this.setBackupStatus('');
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
this.setBackupStatus('busy');
|
this.backups.agents.forEach(function(agent){
|
||||||
|
agent.saveConfig(self.conf, function(){});
|
||||||
this.backups.forEach(function(store){
|
|
||||||
pending++;
|
|
||||||
store.saveConfig(self.conf, function(ok){
|
|
||||||
success &= ok;
|
|
||||||
if (--pending)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.setBackupStatus(success ? 'ok' : 'failed');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setBackupStatus(status)
|
|
||||||
{
|
|
||||||
this.backupStatus = status;
|
|
||||||
if (this.backupCb) this.backupCb.call(this, status);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Storage_Local extends Storage
|
class Storage_Local extends Storage
|
||||||
@@ -2277,6 +2250,9 @@
|
|||||||
if (! meta)
|
if (! meta)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
delete meta.backingUp; // run-time var
|
||||||
|
delete meta.needsBackup; // ditto
|
||||||
|
|
||||||
meta = Object.assign(new BoardMeta(), meta);
|
meta = Object.assign(new BoardMeta(), meta);
|
||||||
this.boardIndex.set(board_id, meta);
|
this.boardIndex.set(board_id, meta);
|
||||||
}
|
}
|
||||||
@@ -2382,12 +2358,17 @@
|
|||||||
*/
|
*/
|
||||||
class BackupStorage
|
class BackupStorage
|
||||||
{
|
{
|
||||||
constructor(id, conf)
|
constructor(id, conf, onStatusChange)
|
||||||
{
|
{
|
||||||
this.type = '?';
|
this.type = '?';
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.conf = conf;
|
this.conf = conf;
|
||||||
|
this.status = '';
|
||||||
|
this.lastOp = '';
|
||||||
|
this.lastXhr = { op: '', text: '', code: 0 };
|
||||||
|
this.onStatusChange = onStatusChange;
|
||||||
|
this.queue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStatus(cb) { return false; }
|
checkStatus(cb) { return false; }
|
||||||
@@ -2398,95 +2379,144 @@
|
|||||||
|
|
||||||
class SimpleBackup extends BackupStorage
|
class SimpleBackup extends BackupStorage
|
||||||
{
|
{
|
||||||
constructor(id, conf)
|
constructor(id, conf, onStatusChange)
|
||||||
{
|
{
|
||||||
super(id, null);
|
super(id, null, onStatusChange);
|
||||||
|
|
||||||
this.type = 'simp';
|
this.type = 'simp';
|
||||||
this.conf = { base: '', auth: '' }
|
this.conf = { base: '', auth: '' }
|
||||||
this.conf = Object.assign(this.conf, conf);
|
this.conf = Object.assign(this.conf, conf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStatus(cb)
|
checkStatus(cb)
|
||||||
{
|
{
|
||||||
var self = this;
|
this.queue.push({
|
||||||
|
what : 'checkStatus',
|
||||||
$.ajax({
|
cb : cb,
|
||||||
url: this.conf.base + '/config',
|
args :
|
||||||
type: 'put',
|
|
||||||
headers: { 'X-Access-Token': this.conf.auth },
|
|
||||||
data:
|
|
||||||
{
|
{
|
||||||
self: document.location.href,
|
url: this.conf.base + '/config',
|
||||||
// conf: -- without the data --
|
type: 'put',
|
||||||
},
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
dataType: 'json'
|
data:
|
||||||
})
|
{
|
||||||
.done(function(d, s, x) { if (cb) cb.call(self, true, x, s, d); })
|
self: document.location.href,
|
||||||
.fail(function(x, s, e) { if (cb) cb.call(self, false, self.patchXhr(x), s, e); })
|
// conf: -- without the data --
|
||||||
|
},
|
||||||
|
dataType: 'json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.runQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfig(conf, cb)
|
saveConfig(conf, cb)
|
||||||
{
|
{
|
||||||
var self = this;
|
this.queue.push({
|
||||||
|
what : 'saveConfig',
|
||||||
$.ajax({
|
cb : cb,
|
||||||
url: this.conf.base + '/config',
|
args :
|
||||||
type: 'put',
|
|
||||||
headers: { 'X-Access-Token': this.conf.auth },
|
|
||||||
data:
|
|
||||||
{
|
{
|
||||||
self: document.location.href,
|
url: this.conf.base + '/config',
|
||||||
conf: JSON.stringify(conf)
|
type: 'put',
|
||||||
},
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
dataType: 'json'
|
data:
|
||||||
})
|
{
|
||||||
.done(function(d, s, x) { if (cb) cb.call(self, true, x, s, d); })
|
self: document.location.href,
|
||||||
.fail(function(x, s, e) { if (cb) cb.call(self, false, self.patchXhr(x), s, e); })
|
conf: JSON.stringify(conf)
|
||||||
|
},
|
||||||
|
dataType: 'json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.runQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveBoard(id, data, meta, cb)
|
saveBoard(id, data, meta, cb)
|
||||||
{
|
{
|
||||||
var self = this;
|
this.queue.push({
|
||||||
|
what : 'saveBoard',
|
||||||
$.ajax({
|
cb : cb,
|
||||||
url: this.conf.base + '/board/' + id,
|
args :
|
||||||
type: 'put',
|
|
||||||
headers: { 'X-Access-Token': this.conf.auth },
|
|
||||||
data:
|
|
||||||
{
|
{
|
||||||
self: document.location.href,
|
url: this.conf.base + '/board/' + id,
|
||||||
data: data ? JSON.stringify(data) : null,
|
type: 'put',
|
||||||
meta: meta ? JSON.stringify(meta) : null
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
},
|
data:
|
||||||
dataType: 'json'
|
{
|
||||||
})
|
self: document.location.href,
|
||||||
.done(function(d, s, x) { if (cb) cb.call(self, true, x, s, d); })
|
data: data ? JSON.stringify(data) : null,
|
||||||
.fail(function(x, s, e) { if (cb) cb.call(self, false, self.patchXhr(x), s, e); })
|
meta: meta ? JSON.stringify(meta) : null
|
||||||
|
},
|
||||||
|
dataType: 'json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.runQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
nukeBoard(id, cb)
|
nukeBoard(id, cb)
|
||||||
{
|
{
|
||||||
var self = this;
|
this.queue.push({
|
||||||
|
what : 'saveBoard',
|
||||||
|
cb : cb,
|
||||||
|
args :
|
||||||
|
{
|
||||||
|
url: this.conf.base + '/board/' + id,
|
||||||
|
type: 'delete',
|
||||||
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$.ajax({
|
this.runQueue();
|
||||||
url: this.conf.base + '/board/' + id,
|
|
||||||
type: 'delete',
|
|
||||||
headers: { 'X-Access-Token': this.conf.auth },
|
|
||||||
})
|
|
||||||
.done(function(d, s, x) { if (cb) cb.call(self, true, x, s, d); })
|
|
||||||
.fail(function(x, s, e) { if (cb) cb.call(self, false, self.patchXhr(x), s, e); })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* private
|
* private
|
||||||
*/
|
*/
|
||||||
patchXhr(x)
|
runQueue()
|
||||||
{
|
{
|
||||||
if (! x.responseText)
|
var self = this;
|
||||||
x.responseText = x.status ? `Request failed with ${x.status}` : 'Offline or CORS-blocked';
|
|
||||||
return x;
|
if (! this.queue.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.status == 'busy')
|
||||||
|
return;
|
||||||
|
|
||||||
|
var req = this.queue.shift();
|
||||||
|
|
||||||
|
this.setStatus('busy', req.what);
|
||||||
|
|
||||||
|
$.ajax(req.args)
|
||||||
|
.done(function(d, s, x) { self.onRequestDone(req, true, x); })
|
||||||
|
.fail(function(x, s, e) { self.onRequestDone(req, false, x); })
|
||||||
|
}
|
||||||
|
|
||||||
|
onRequestDone(req, ok, xhr)
|
||||||
|
{
|
||||||
|
console.log( `Backup agent '${this.id}', ${this.lastOp}() -> ${ok ? 'ok' : 'failed'}` );
|
||||||
|
|
||||||
|
var code = xhr.status;
|
||||||
|
var text = xhr.responseText || (code ? `Response code ${code}` : 'Offline or CORS-blocked');
|
||||||
|
|
||||||
|
this.lastXhr = { text: text, code: code };
|
||||||
|
|
||||||
|
this.setStatus(ok ? 'ready' : 'error', this.lastOp);
|
||||||
|
|
||||||
|
if (req.cb) req.cb.call(this);
|
||||||
|
|
||||||
|
this.runQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(status, op)
|
||||||
|
{
|
||||||
|
if (status == 'busy' && this.status == 'busy')
|
||||||
|
throw `Backup agent ${this.id} is already busy!`;
|
||||||
|
|
||||||
|
this.status = status;
|
||||||
|
this.lastOp = op;
|
||||||
|
this.onStatusChange(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3093,6 +3123,9 @@
|
|||||||
|
|
||||||
function closeBoard(quick)
|
function closeBoard(quick)
|
||||||
{
|
{
|
||||||
|
if (! NB.board)
|
||||||
|
return;
|
||||||
|
|
||||||
var $board = $('.wrap .board');
|
var $board = $('.wrap .board');
|
||||||
|
|
||||||
if (quick)
|
if (quick)
|
||||||
@@ -3429,20 +3462,20 @@
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function findBackup(which)
|
function findBackupAgent(which)
|
||||||
{
|
{
|
||||||
var s = null;
|
var a = null;
|
||||||
|
|
||||||
NB.storage.backups.forEach(function(store){
|
NB.storage.backups.agents.forEach(function(agent){
|
||||||
if (store.type == which.type &&
|
if (agent.type == which.type &&
|
||||||
store.conf.auth == which.conf.auth &&
|
agent.conf.auth == which.conf.auth &&
|
||||||
store.conf.base == which.conf.base)
|
agent.conf.base == which.conf.base)
|
||||||
{
|
{
|
||||||
s = store;
|
a = agent;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return s;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBackupConfigUi($div, backupConf)
|
function setBackupConfigUi($div, backupConf)
|
||||||
@@ -3454,7 +3487,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var $status = $div.find('.status');
|
var $status = $div.find('.status');
|
||||||
var b = findBackup(backupConf);
|
var b = findBackupAgent(backupConf);
|
||||||
var text = 'OK';
|
var text = 'OK';
|
||||||
|
|
||||||
if (b && b.last && ! b.last.ok)
|
if (b && b.last && ! b.last.ok)
|
||||||
@@ -3470,15 +3503,16 @@
|
|||||||
function getBackupConfigUi()
|
function getBackupConfigUi()
|
||||||
{
|
{
|
||||||
var conf = NB.storage.getConfig();
|
var conf = NB.storage.getConfig();
|
||||||
var loc = conf.backups[0];
|
var loc = conf.backups.agents[0];
|
||||||
var rem = conf.backups[1];
|
var rem = conf.backups.agents[1];
|
||||||
|
|
||||||
var $div = $('.overlay .backup-conf');
|
var $div = $('.overlay .backup-conf');
|
||||||
var $loc = $div.find('.loc');
|
var $loc = $div.find('.loc');
|
||||||
var $rem = $div.find('.rem');
|
var $rem = $div.find('.rem');
|
||||||
|
|
||||||
var ret = {
|
var ret =
|
||||||
loc: jsonClone(loc),
|
{
|
||||||
|
loc: jsonClone(loc),
|
||||||
rem: jsonClone(rem)
|
rem: jsonClone(rem)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3522,16 +3556,17 @@
|
|||||||
$div.delay(850).queue(function(){
|
$div.delay(850).queue(function(){
|
||||||
|
|
||||||
var T = NB.backupTypes.get(backupConf.type);
|
var T = NB.backupTypes.get(backupConf.type);
|
||||||
var foo = new T(backupConf.id, backupConf.conf);
|
var foo = new T(backupConf.id, backupConf.conf, function(){});
|
||||||
|
|
||||||
foo.checkStatus(function(ok, xhr){
|
foo.checkStatus(function(){
|
||||||
if (ok)
|
|
||||||
|
if (foo.status == 'ready')
|
||||||
{
|
{
|
||||||
$text.val('OK');
|
$text.val('OK');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$text.val(xhr.responseText);
|
$text.val(foo.lastXhr.text);
|
||||||
$status.addClass('error');
|
$status.addClass('error');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3546,8 +3581,8 @@
|
|||||||
{
|
{
|
||||||
var conf = NB.storage.getConfig();
|
var conf = NB.storage.getConfig();
|
||||||
|
|
||||||
if (conf.backups.length != 2)
|
if (conf.backups.agents.length != 2)
|
||||||
throw 'Invalid conf.backups[]'; // as per fixupConfig()
|
throw 'Invalid conf.backups.agents[]'; // as per fixupConfig()
|
||||||
|
|
||||||
//
|
//
|
||||||
var $div = $('tt .backup-conf').clone();
|
var $div = $('tt .backup-conf').clone();
|
||||||
@@ -3557,8 +3592,8 @@
|
|||||||
var $rem = $div.find('.rem');
|
var $rem = $div.find('.rem');
|
||||||
|
|
||||||
var typ = (new SimpleBackup).type;
|
var typ = (new SimpleBackup).type;
|
||||||
var loc = conf.backups[0];
|
var loc = conf.backups.agents[0];
|
||||||
var rem = conf.backups[1];
|
var rem = conf.backups.agents[1];
|
||||||
|
|
||||||
div.checking = 0;
|
div.checking = 0;
|
||||||
|
|
||||||
@@ -3641,16 +3676,16 @@
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (foo.loc.enabled && ! loc.enabled)
|
if (foo.loc.enabled && ! loc.enabled)
|
||||||
foo.loc.id = typ + '-' + (conf.nextBackupId++);
|
foo.loc.id = typ + '-' + (conf.backups.nextId++);
|
||||||
|
|
||||||
if (foo.rem.enabled && ! rem.enabled)
|
if (foo.rem.enabled && ! rem.enabled)
|
||||||
foo.rem.id = typ + '-' + (conf.nextBackupId++);
|
foo.rem.id = typ + '-' + (conf.backups.nextId++);
|
||||||
|
|
||||||
conf.backups[0] = foo.loc;
|
conf.backups.agents[0] = foo.loc;
|
||||||
conf.backups[1] = foo.rem;
|
conf.backups.agents[1] = foo.rem;
|
||||||
|
|
||||||
|
NB.storage.initBackups(onBackupStatusChange);
|
||||||
NB.storage.saveConfig();
|
NB.storage.saveConfig();
|
||||||
NB.storage.initBackups(onBackupStatus);
|
|
||||||
|
|
||||||
hideOverlay();
|
hideOverlay();
|
||||||
});
|
});
|
||||||
@@ -3662,14 +3697,17 @@
|
|||||||
showOverlay($div);
|
showOverlay($div);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBackupStatus(_status)
|
function onBackupStatusChange(agent)
|
||||||
{
|
{
|
||||||
var backups = NB.storage.backups;
|
var agents = NB.storage.backups.agents;
|
||||||
var status = NB.storage.backupStatus;
|
|
||||||
var $config = $('.config');
|
var $config = $('.config');
|
||||||
var $status = $('.config .teaser u')
|
var $status = $('.config .teaser u')
|
||||||
|
|
||||||
if (! backups.length)
|
// if (agent) console.log( `onBackupStatusChange: ${agent.id}, status ${agent.status}, op ${agent.lastOp}, xhr '${agent.lastXhr.text}' / ${agent.lastXhr.code}` );
|
||||||
|
// else console.log( `onBackupStatusChange: <generic>` );
|
||||||
|
|
||||||
|
if (! agents.length)
|
||||||
{
|
{
|
||||||
$config.removeClass('backups-on backup-err backing-up');
|
$config.removeClass('backups-on backup-err backing-up');
|
||||||
return;
|
return;
|
||||||
@@ -3677,13 +3715,51 @@
|
|||||||
|
|
||||||
$config.addClass('backups-on');
|
$config.addClass('backups-on');
|
||||||
|
|
||||||
if (status == 'failed') $config.addClass('backup-err').removeClass('backing-up'); else
|
var busy = 0;
|
||||||
if (status == 'busy') $config.addClass('backing-up').removeClass('backup-err'); else
|
var error = 0;
|
||||||
if (status == 'ok') $config.removeClass('backing-up backup-err');
|
var ready = 0;
|
||||||
|
|
||||||
// if become 'ok' - process all pending backups
|
agents.forEach(function(agent){
|
||||||
|
if (agent.status == 'busy') busy++; else
|
||||||
|
if (agent.status == 'error') error++; else
|
||||||
|
if (agent.status == 'ready') ready++; else
|
||||||
|
throw `Unknown status [${agent.status}] on backup agent ${agent.id}`;
|
||||||
|
});
|
||||||
|
|
||||||
// ...
|
if (error > 0) $config.addClass('backup-err').removeClass('backing-up'); else
|
||||||
|
if (busy > 0) $config.addClass('backing-up').removeClass('backup-err'); else
|
||||||
|
$config.removeClass('backing-up backup-err');
|
||||||
|
|
||||||
|
// process all pending backups if needed
|
||||||
|
|
||||||
|
if (! error && ! busy)
|
||||||
|
runPendingBackups();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPendingBackups()
|
||||||
|
{
|
||||||
|
// var boards = NB.storage.getBoardIndex();
|
||||||
|
// var backups = NB.storage.backups;
|
||||||
|
// var backupSet = [];
|
||||||
|
//
|
||||||
|
// backups.forEach(function(b){ backupSet.push(b.id); });
|
||||||
|
// backupSet.sort();
|
||||||
|
//
|
||||||
|
// console.log('Checking for pending backups. Current backup set - ', backupSet);
|
||||||
|
//
|
||||||
|
// boards.forEach(function(meta, id){
|
||||||
|
//
|
||||||
|
// var backItUp = false;
|
||||||
|
//
|
||||||
|
// if (! meta.needsBackup && jsonMatch(meta.backups.sort(), backupSet))
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// console.log( `Board ${id} may need a backup`, meta.backups );
|
||||||
|
//
|
||||||
|
// var board = NB.storage.loadBoard(id);
|
||||||
|
// if (board)
|
||||||
|
// NB.storage.backupBoard(id, board, meta)
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4860,7 +4936,7 @@
|
|||||||
console.log( `Active: [${conf.board}]` );
|
console.log( `Active: [${conf.board}]` );
|
||||||
console.log( `Theme: [${conf.theme}]` );
|
console.log( `Theme: [${conf.theme}]` );
|
||||||
console.log( `Font: [${conf.fontName}], size [${conf.fontSize || '-'}], line-height [${conf.lineHeight || '-'}]` );
|
console.log( `Font: [${conf.fontName}], size [${conf.fontSize || '-'}], line-height [${conf.lineHeight || '-'}]` );
|
||||||
console.log( 'Backups: ' + JSON.stringify(conf.backups));
|
console.log( 'Backups: ', conf.backups);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* backups
|
* backups
|
||||||
@@ -4868,7 +4944,7 @@
|
|||||||
NB.backupTypes = new Map();
|
NB.backupTypes = new Map();
|
||||||
NB.backupTypes.set( (new SimpleBackup).type, SimpleBackup );
|
NB.backupTypes.set( (new SimpleBackup).type, SimpleBackup );
|
||||||
|
|
||||||
NB.storage.initBackups(onBackupStatus);
|
NB.storage.initBackups(onBackupStatusChange);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the ui
|
* the ui
|
||||||
|
Reference in New Issue
Block a user