Backup transfer/retrieval process
This commit is contained in:
parent
9fd1ae49c2
commit
626c9ec214
11
src/app.js
11
src/app.js
@ -81,16 +81,13 @@ module.exports = function App(secret, DB) {
|
|||||||
var periodInstance = null;
|
var periodInstance = null;
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
//return server, express-app, wss
|
//return server, express-app
|
||||||
Object.defineProperty(self, "server", {
|
Object.defineProperty(self, "server", {
|
||||||
get: () => server
|
get: () => server
|
||||||
});
|
});
|
||||||
Object.defineProperty(self, "express", {
|
Object.defineProperty(self, "express", {
|
||||||
get: () => app
|
get: () => app
|
||||||
});
|
});
|
||||||
Object.defineProperty(self, "wss", {
|
|
||||||
get: () => wss
|
|
||||||
});
|
|
||||||
|
|
||||||
//set trustedID for subAdmin requests
|
//set trustedID for subAdmin requests
|
||||||
Object.defineProperty(self, "trustedIDs", {
|
Object.defineProperty(self, "trustedIDs", {
|
||||||
@ -100,17 +97,13 @@ module.exports = function App(secret, DB) {
|
|||||||
//Start (or) Stop servers
|
//Start (or) Stop servers
|
||||||
self.start = (port) => new Promise(resolve => {
|
self.start = (port) => new Promise(resolve => {
|
||||||
server = app.listen(port, () => {
|
server = app.listen(port, () => {
|
||||||
wss = new WebSocket.Server({
|
|
||||||
server
|
|
||||||
});
|
|
||||||
resolve(`Server Running at port ${port}`);
|
resolve(`Server Running at port ${port}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
self.stop = () => new Promise(resolve => {
|
self.stop = () => new Promise(resolve => {
|
||||||
server.close(() => {
|
server.close(() => {
|
||||||
server = null;
|
server = null;
|
||||||
wss = null;
|
resolve('Server stopped');
|
||||||
resolve('Server stopped')
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4,22 +4,36 @@ const WAIT_TIME = 30 * 60 * 1000,
|
|||||||
BACKUP_INTERVAL = 10 * 60 * 1000;
|
BACKUP_INTERVAL = 10 * 60 * 1000;
|
||||||
|
|
||||||
var DB; //Container for Database connection
|
var DB; //Container for Database connection
|
||||||
var masterWS; //Container for Master websocket connection
|
var masterWS = null; //Container for Master websocket connection
|
||||||
|
|
||||||
var intervalID = null;
|
var intervalID = null;
|
||||||
|
|
||||||
function startIntervalSync(ws) {
|
function startSlaveProcess(ws) {
|
||||||
|
if (!ws) throw Error("Master WS connection required");
|
||||||
|
//stop existing process
|
||||||
|
stopSlaveProcess();
|
||||||
//set masterWS
|
//set masterWS
|
||||||
ws.on('message', processDataFromMaster);
|
ws.on('message', processDataFromMaster);
|
||||||
masterWS = ws;
|
masterWS = ws;
|
||||||
//stop existing sync
|
//inform master
|
||||||
stopIntervalSync();
|
let message = {
|
||||||
|
floID: global.floID,
|
||||||
|
pubKey: global.pubKey,
|
||||||
|
req_time: Date.now(),
|
||||||
|
type: "SLAVE_CONNECT"
|
||||||
|
}
|
||||||
|
message.sign = floCrypto.signData(message.type + "|" + message.req_time, global.myPrivKey);
|
||||||
//start sync
|
//start sync
|
||||||
requestInstance.open();
|
requestInstance.open();
|
||||||
intervalID = setInterval(requestInstance.open, BACKUP_INTERVAL);
|
intervalID = setInterval(requestInstance.open, BACKUP_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopIntervalSync() {
|
function stopSlaveProcess() {
|
||||||
|
if (masterWS !== null) {
|
||||||
|
masterWS.onclose = () => null;
|
||||||
|
masterWS.close();
|
||||||
|
masterWS = null;
|
||||||
|
}
|
||||||
if (intervalID !== null) {
|
if (intervalID !== null) {
|
||||||
clearInterval(intervalID);
|
clearInterval(intervalID);
|
||||||
intervalID = null;
|
intervalID = null;
|
||||||
@ -40,13 +54,13 @@ function requestBackupSync(ws) {
|
|||||||
subs.push(`SELECT MAX(${tables[t]}) as ts FROM ${t}`);
|
subs.push(`SELECT MAX(${tables[t]}) as ts FROM ${t}`);
|
||||||
DB.query(`SELECT MAX(ts) as last_time FROM (${subs.join(' UNION ')}) AS Z`).then(result => {
|
DB.query(`SELECT MAX(ts) as last_time FROM (${subs.join(' UNION ')}) AS Z`).then(result => {
|
||||||
let request = {
|
let request = {
|
||||||
floID: myFloID,
|
floID: global.myFloID,
|
||||||
pubKey: myPubKey,
|
pubKey: myPubKey,
|
||||||
type: "BACKUP_SYNC",
|
type: "BACKUP_SYNC",
|
||||||
last_time: result[0].last_time,
|
last_time: result[0].last_time,
|
||||||
req_time: Date.now()
|
req_time: Date.now()
|
||||||
};
|
};
|
||||||
request.sign = floCrypto.signData(request.type + "|" + request.req_time, myPrivKey);
|
request.sign = floCrypto.signData(request.type + "|" + request.req_time, global.myPrivKey);
|
||||||
console.debug("REQUEST: ", request);
|
console.debug("REQUEST: ", request);
|
||||||
ws.send(JSON.stringify(request));
|
ws.send(JSON.stringify(request));
|
||||||
resolve(request);
|
resolve(request);
|
||||||
@ -101,17 +115,46 @@ function processDataFromMaster(message) {
|
|||||||
try {
|
try {
|
||||||
message = JSON.parse(message);
|
message = JSON.parse(message);
|
||||||
console.debug(message);
|
console.debug(message);
|
||||||
if (message.mode.startsWith("SYNC"))
|
if (message.command.startsWith("SYNC"))
|
||||||
processBackupData(message);
|
processBackupData(message);
|
||||||
|
else switch (message.command) {
|
||||||
|
case "SINK_SHARE":
|
||||||
|
storeSinkShare(message);
|
||||||
|
break;
|
||||||
|
case "SEND_SHARE":
|
||||||
|
sendSinkShare();
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function storeSinkShare(message) {
|
||||||
|
console.debug(Date.now(), '|sinkID:', message.sinkID, '|share:', message.keyShare);
|
||||||
|
DB.query("INSERT INTO sinkShares (floID, share) VALUE (?, ?)", [message.sinkID, message.keyShare])
|
||||||
|
.then(_ => null).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendSinkShare() {
|
||||||
|
DB.query("SELECT floID, share FROM sinkShares ORDER BY time_ DESC LIMIT 1").then(result => {
|
||||||
|
let response = {
|
||||||
|
type: "SINK_SHARE",
|
||||||
|
sinkID: result[0].floID,
|
||||||
|
share: result[0].share,
|
||||||
|
floID: global.myFloID,
|
||||||
|
pubKey: global.pubKey,
|
||||||
|
req_time: Date.now()
|
||||||
|
}
|
||||||
|
response.sign = floCrypto.signData(response.type + "|" + response.req_time, global.myPrivKey); //TODO: strengthen signature
|
||||||
|
masterWS.send(JSON.stringify(response));
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
function processBackupData(response) {
|
function processBackupData(response) {
|
||||||
const self = requestInstance;
|
const self = requestInstance;
|
||||||
self.last_response_time = Date.now();
|
self.last_response_time = Date.now();
|
||||||
switch (response.mode) {
|
switch (response.command) {
|
||||||
case "SYNC_ERROR":
|
case "SYNC_ERROR":
|
||||||
console.log(response.error);
|
console.log(response.error);
|
||||||
self.close();
|
self.close();
|
||||||
@ -201,6 +244,9 @@ module.exports = {
|
|||||||
set DB(db) {
|
set DB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
},
|
},
|
||||||
start: startIntervalSync,
|
get masterWS() {
|
||||||
stop: stopIntervalSync
|
return masterWS;
|
||||||
|
},
|
||||||
|
start: startSlaveProcess,
|
||||||
|
stop: stopSlaveProcess
|
||||||
}
|
}
|
||||||
@ -1,7 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const shareThreshold = 70 / 100;
|
const slave = require('./storage');
|
||||||
|
const WebSocket = require('ws');
|
||||||
|
const shareThreshold = 50 / 100;
|
||||||
|
|
||||||
var DB; //Container for database
|
var DB, app, wss; //Container for database and app
|
||||||
|
var nodeShares = null,
|
||||||
|
nodeSinkID = null,
|
||||||
|
connectedSlaves = {},
|
||||||
|
mod = null;
|
||||||
|
const SLAVE_MODE = 0,
|
||||||
|
MASTER_MODE = 1;
|
||||||
|
|
||||||
//Backup Transfer
|
//Backup Transfer
|
||||||
function sendBackup(timestamp, ws) {
|
function sendBackup(timestamp, ws) {
|
||||||
@ -19,14 +27,14 @@ function sendBackup(timestamp, ws) {
|
|||||||
if (failedSync.length) {
|
if (failedSync.length) {
|
||||||
console.info("Backup Sync Failed:", failedSync);
|
console.info("Backup Sync Failed:", failedSync);
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
mode: "SYNC_END",
|
command: "SYNC_END",
|
||||||
status: false,
|
status: false,
|
||||||
info: failedSync
|
info: failedSync
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
console.info("Backup Sync completed");
|
console.info("Backup Sync completed");
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
mode: "SYNC_END",
|
command: "SYNC_END",
|
||||||
status: true
|
status: true
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -37,7 +45,7 @@ function send_deleteSync(timestamp, ws) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
DB.query("SELECT * FROM _backup WHERE mode is NULL AND timestamp > ?", [timestamp]).then(result => {
|
DB.query("SELECT * FROM _backup WHERE mode is NULL AND timestamp > ?", [timestamp]).then(result => {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
mode: "SYNC_DELETE",
|
command: "SYNC_DELETE",
|
||||||
delete_data: result
|
delete_data: result
|
||||||
}));
|
}));
|
||||||
resolve("deleteSync");
|
resolve("deleteSync");
|
||||||
@ -54,7 +62,7 @@ function send_dataSync(timestamp, ws) {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
table,
|
table,
|
||||||
mode: "SYNC_ADD_UPDATE",
|
command: "SYNC_ADD_UPDATE",
|
||||||
data
|
data
|
||||||
}));
|
}));
|
||||||
res(table);
|
res(table);
|
||||||
@ -68,7 +76,7 @@ function send_dataSync(timestamp, ws) {
|
|||||||
let sync_needed = {};
|
let sync_needed = {};
|
||||||
result.forEach(r => r.t_name in sync_needed ? sync_needed[r.t_name].push(r.id) : sync_needed[r.t_name] = [r.id]);
|
result.forEach(r => r.t_name in sync_needed ? sync_needed[r.t_name].push(r.id) : sync_needed[r.t_name] = [r.id]);
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
mode: "SYNC_ADD_UPDATE_HEADER",
|
command: "SYNC_ADD_UPDATE_HEADER",
|
||||||
add_data: result
|
add_data: result
|
||||||
}));
|
}));
|
||||||
let promises = [];
|
let promises = [];
|
||||||
@ -101,7 +109,7 @@ function send_dataImmutable(timestamp, ws) {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
table,
|
table,
|
||||||
mode: "SYNC_ADD_IMMUTABLE",
|
command: "SYNC_ADD_IMMUTABLE",
|
||||||
data
|
data
|
||||||
}));
|
}));
|
||||||
res(table);
|
res(table);
|
||||||
@ -129,7 +137,7 @@ function send_dataImmutable(timestamp, ws) {
|
|||||||
//Shares
|
//Shares
|
||||||
function generateNewSink() {
|
function generateNewSink() {
|
||||||
let sink = floCrypto.generateNewID();
|
let sink = floCrypto.generateNewID();
|
||||||
let nextNodes = KB.nextNode(myFloID, null);
|
let nextNodes = KB.nextNode(global.myFloID, null);
|
||||||
let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold));
|
let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold));
|
||||||
sink.shares = {};
|
sink.shares = {};
|
||||||
for (let i in nextNodes)
|
for (let i in nextNodes)
|
||||||
@ -137,7 +145,7 @@ function generateNewSink() {
|
|||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendShare(ws, sinkID, share) {
|
function sendShare(ws, sinkID, keyShare) {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
command: "SINK_SHARE",
|
command: "SINK_SHARE",
|
||||||
sinkID,
|
sinkID,
|
||||||
@ -145,9 +153,142 @@ function sendShare(ws, sinkID, share) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendSharesToNodes(sinkID, shares) {
|
||||||
|
nodeSinkID = sinkID;
|
||||||
|
nodeShares = shares;
|
||||||
|
for (let node in shares)
|
||||||
|
if (node in connectedSlaves)
|
||||||
|
sendShare(connectedSlaves[node], sinkID, shares[node]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeSink(sinkID, sinkPrivKey) {
|
||||||
|
global.sinkID = sinkID;
|
||||||
|
global.sinkPrivKey = sinkPrivKey;
|
||||||
|
let encryptedKey = Crypto.AES.encrypt(sinkPrivKey, global.myPrivKey);
|
||||||
|
DB.query('INSERT INTO sinkShares (floID, share) VALUE (?, ?)', [sinkID, '$$$' + encryptedKey])
|
||||||
|
.then(_ => console.log('SinkID:', sinkID, '|SinkEnKey:', encryptedKey))
|
||||||
|
.catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferMoneyToNewSink(oldSinkID, oldSinkKey) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let newSink = generateNewSink();
|
||||||
|
floBlockchainAPI.getBalance(oldSinkID).then(balFLO => {
|
||||||
|
tokenAPI.getBalance(oldSinkID).then(balRupee => {
|
||||||
|
floBlockchainAPI.sendTx(oldSinkID, newSink.floID, balFLO - floGlobals.fee, oldSinkKey, `send ${balRupee} ${floGlobals.token}# |Exchange-market New sink`)
|
||||||
|
.then(result => resolve(newSink))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectShares(floID, sinkID, share) {
|
||||||
|
if (!collectShares.sinkID) {
|
||||||
|
collectShares.sinkID = sinkID;
|
||||||
|
collectShares.shares = {};
|
||||||
|
} else if (collectShares.sinkID !== sinkID)
|
||||||
|
return console.error("Something is wrong! Slaves are sending different sinkID");
|
||||||
|
collectShares.shares[floID] = share;
|
||||||
|
try {
|
||||||
|
let privKey = floCrypto.retrieveShamirSecret(Object.values(collectShares.shares));
|
||||||
|
if (floCrypto.verifyPrivKey(privKey, collectShares.sinkID)) {
|
||||||
|
transferMoneyToNewSink(collectShares.sinkID, privKey).then(newSink => {
|
||||||
|
delete collectShares.sinkID;
|
||||||
|
delete collectShares.shares;
|
||||||
|
collectShares.active = false;
|
||||||
|
storeSink(newSink.floID, newSink.privKey);
|
||||||
|
sendSharesToNodes(newSink.floID, newSink.shares);
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
//Unable to retrive sink private key. Waiting for more shares! Do nothing for now
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectWS(floID) {
|
||||||
|
let url = nodeURL[floID];
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const ws = new WebSocket(url);
|
||||||
|
ws.on('open', _ => resolve(ws));
|
||||||
|
ws.on('error', _ => reject(error));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectToMaster(i = 0) {
|
||||||
|
if (i >= nodeList.length) {
|
||||||
|
console.error("No master is found, and myFloID is not in list. This should not happen!");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
let floID = nodeList[i];
|
||||||
|
if (floID === myFloID)
|
||||||
|
serveAsMaster();
|
||||||
|
else
|
||||||
|
connectWS(floID).then(ws => {
|
||||||
|
ws.floID = floID;
|
||||||
|
ws.onclose = () => connectToMaster(i);
|
||||||
|
serveAsSlave(ws);
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(`Node(${floID}) is offline`);
|
||||||
|
connectToMaster(i + 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Node becomes master
|
||||||
|
function serveAsMaster() {
|
||||||
|
app.resume();
|
||||||
|
slave.stop();
|
||||||
|
mod = MASTER_MODE;
|
||||||
|
informLiveNodes();
|
||||||
|
collectShares.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function serveAsSlave(ws) {
|
||||||
|
app.pause();
|
||||||
|
slave.start(ws);
|
||||||
|
mod = SLAVE_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function informLiveNodes() {
|
||||||
|
let message = {
|
||||||
|
floID: global.myFloID,
|
||||||
|
type: "UPDATE_MASTER",
|
||||||
|
pubKey: global.myPubKey,
|
||||||
|
req_time: Date.now()
|
||||||
|
};
|
||||||
|
message.sign = floCrypto.signData(message.type + "|" + message.req_time, global.myPrivKey);
|
||||||
|
message = JSON.stringify(message);
|
||||||
|
for (let n in nodeURL)
|
||||||
|
if (n !== global.myFloID)
|
||||||
|
connectWS(n).then(ws => {
|
||||||
|
ws.send(message);
|
||||||
|
ws.close();
|
||||||
|
}).catch(error => console.warn(`Node ${n} is offline`));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMaster(floID) {
|
||||||
|
let currentMaster = mod === MASTER_MODE ? global.floID : slave.masterWS.floID;
|
||||||
|
if (nodeList.indexOf(floID) < nodeList.indexOf(currentMaster))
|
||||||
|
connectToMaster();
|
||||||
|
}
|
||||||
|
|
||||||
|
function slaveConnect(floID, ws) {
|
||||||
|
ws.floID = floID;
|
||||||
|
connectedSlaves[floID] = ws;
|
||||||
|
if (collectShares.active)
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
command: "SEND_SHARE"
|
||||||
|
}));
|
||||||
|
else if (nodeShares[floID])
|
||||||
|
sendShare(ws, nodeSinkID, nodeShares[floID]);
|
||||||
|
}
|
||||||
|
|
||||||
//Transmistter
|
//Transmistter
|
||||||
var nodeList; //Container for (backup) node list
|
var nodeList; //Container for (backup) node list
|
||||||
function startBackupTransmitter(wss) {
|
function startBackupTransmitter(server) {
|
||||||
|
wss = new WebSocket.Server({
|
||||||
|
server
|
||||||
|
});
|
||||||
wss.on('connection', ws => {
|
wss.on('connection', ws => {
|
||||||
ws.on('message', message => {
|
ws.on('message', message => {
|
||||||
//verify if from a backup node
|
//verify if from a backup node
|
||||||
@ -155,38 +296,64 @@ function startBackupTransmitter(wss) {
|
|||||||
let invalid = null,
|
let invalid = null,
|
||||||
request = JSON.parse(message);
|
request = JSON.parse(message);
|
||||||
console.debug(request);
|
console.debug(request);
|
||||||
if (!backupIDs.includes(request.floID))
|
if (!nodeList.includes(request.floID))
|
||||||
invalid = "FLO ID not approved for backup";
|
invalid = `floID ${request.floID} not in nodeList`;
|
||||||
else if (request.floID !== floCrypto.getFloID(request.pubKey))
|
else if (request.floID !== floCrypto.getFloID(request.pubKey))
|
||||||
invalid = "Invalid pubKey";
|
invalid = "Invalid pubKey";
|
||||||
else if (!floCrypto.verifySign(request.type + "|" + request.req_time, request.sign, request.pubKey))
|
else if (!floCrypto.verifySign(request.type + "|" + request.req_time, request.sign, request.pubKey))
|
||||||
invalid = "Invalid signature";
|
invalid = "Invalid signature";
|
||||||
else if (request.type !== "BACKUP_SYNC")
|
|
||||||
invalid = "Invalid Request Type";
|
|
||||||
//TODO: check if request time is valid;
|
//TODO: check if request time is valid;
|
||||||
|
else switch (request.type) {
|
||||||
|
case "BACKUP_SYNC":
|
||||||
|
sendBackup(request.last_time, ws);
|
||||||
|
break;
|
||||||
|
case "UPDATE_MASTER":
|
||||||
|
updateMaster(request.floID);
|
||||||
|
break;
|
||||||
|
case "SLAVE_CONNECT":
|
||||||
|
slaveConnect(request.floID, ws);
|
||||||
|
break;
|
||||||
|
case "SINK_SHARE":
|
||||||
|
collectShares(request.floID, request.sinkID, request.share)
|
||||||
|
default:
|
||||||
|
invalid = "Invalid Request Type";
|
||||||
|
}
|
||||||
if (invalid)
|
if (invalid)
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
error: invalid
|
error: invalid
|
||||||
}));
|
}));
|
||||||
else
|
|
||||||
sendBackup(request.last_time, ws);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
mode: "SYNC_ERROR",
|
command: "SYNC_ERROR",
|
||||||
error: 'Unable to process the request!'
|
error: 'Unable to process the request!'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ws.on('close', () => {
|
||||||
|
// remove from connected slaves (if needed)
|
||||||
|
if (ws.floID in connectedSlaves)
|
||||||
|
delete connectedSlaves[ws.floID];
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initProcess(a) {
|
||||||
|
app = a;
|
||||||
|
startBackupTransmitter(app.server);
|
||||||
|
connectToMaster();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: startBackupTransmitter,
|
init: initProcess,
|
||||||
set nodeList(ids) {
|
set nodeList(ids) {
|
||||||
nodeList = ids;
|
nodeList = ids;
|
||||||
},
|
},
|
||||||
set DB(db) {
|
set DB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
|
slave.DB = db;
|
||||||
|
},
|
||||||
|
get wss() {
|
||||||
|
return wss;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
44
src/main.js
44
src/main.js
@ -4,13 +4,13 @@ require('./set_globals');
|
|||||||
require('./lib');
|
require('./lib');
|
||||||
require('./floCrypto');
|
require('./floCrypto');
|
||||||
require('./floBlockchainAPI');
|
require('./floBlockchainAPI');
|
||||||
|
require('./tokenAPI');
|
||||||
|
|
||||||
const Database = require("./database");
|
const Database = require("./database");
|
||||||
const App = require('./app');
|
const App = require('./app');
|
||||||
const PORT = config['port'];
|
const PORT = config['port'];
|
||||||
|
|
||||||
const K_Bucket = require('./backup/KBucket');
|
const K_Bucket = require('./backup/KBucket');
|
||||||
const slave = require('./backup/storage');
|
|
||||||
const transmit = require('./backup/transmit');
|
const transmit = require('./backup/transmit');
|
||||||
|
|
||||||
var DB, app;
|
var DB, app;
|
||||||
@ -134,48 +134,9 @@ loadDataFromDB.trustedIDs = function() {
|
|||||||
|
|
||||||
function setDB(db) {
|
function setDB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
slave.DB = DB;
|
|
||||||
transmit.DB = DB;
|
transmit.DB = DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectWS(floID) {
|
|
||||||
let url = nodeURL[floID];
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const ws = new WebSocket(url);
|
|
||||||
ws.on('open', _ => resolve(ws));
|
|
||||||
ws.on('error', _ => reject(error));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function connectToMaster(i = 0) {
|
|
||||||
if (i >= nodeList.length) {
|
|
||||||
console.error("No master is found, and myFloID is not in list. This should not happen!");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
let floID = nodeList[i];
|
|
||||||
if (floID === myFloID)
|
|
||||||
serveAsMaster();
|
|
||||||
else
|
|
||||||
connectWS(floID).then(ws => {
|
|
||||||
ws.floID = floID;
|
|
||||||
ws.onclose = () => connectToMaster(i);
|
|
||||||
serveAsSlave(ws);
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(`Node(${floID}) is offline`);
|
|
||||||
connectToMaster(i + 1)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function serveAsMaster() {
|
|
||||||
app.resume();
|
|
||||||
slave.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
function serveAsSlave(masterWS) {
|
|
||||||
app.pause();
|
|
||||||
slave.start(masterWS);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function startServer(public_dir) {
|
module.exports = function startServer(public_dir) {
|
||||||
try {
|
try {
|
||||||
var _tmp = require('../args/keys.json');
|
var _tmp = require('../args/keys.json');
|
||||||
@ -208,8 +169,7 @@ module.exports = function startServer(public_dir) {
|
|||||||
refreshData(true).then(_ => {
|
refreshData(true).then(_ => {
|
||||||
app.start(PORT).then(result => {
|
app.start(PORT).then(result => {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
transmit.init(app.wss);
|
transmit.init(app);
|
||||||
connectToMaster();
|
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user