feat(@embark/storage): Add command `service swarm on/off`

Add support for ability to start and stop Swarm via command `service swarm on/off`.

Fix issue with swarm not starting due to missing web3 object.

`service swarm on` - starts a swarm node if not already started. Shows an error if the node is already starting or started.

`service swarm off` - kills the running swarm node as long as Embark has started the swarm process. If the swarm process was started externally, an error is shown.
This commit is contained in:
emizzle 2019-05-03 17:43:21 +10:00 committed by Iuri Matias
parent b5db6857a8
commit 3dcc339e4d
5 changed files with 65 additions and 19 deletions

View File

@ -41,7 +41,7 @@ class Storage {
}
addSetProviders(cb) {
let code = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.storageConfig.dappConnection || [])});`;
let code = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.storageConfig.dappConnection || [])}, {web3});`;
let shouldInit = (storageConfig) => {
return storageConfig.enabled;

View File

@ -17,6 +17,11 @@ class Swarm {
this.port = this.storageConfig.port;
this.embark = embark;
this.fs = embark.fs;
this.isServiceRegistered = false;
this.addedToEmbarkJs = false;
this.addedToConsole = false;
this.storageProcessesLauncher = null;
this.usingRunningNode = false;
this.webServerConfig = embark.config.webServerConfig;
this.blockchainConfig = embark.config.blockchainConfig;
@ -49,18 +54,44 @@ class Swarm {
this.registerUploadCommand();
this.listenToCommands();
this.registerConsoleCommands();
this.events.request("processes:register", "swarm", {
launchFn: (cb) => {
if(this.usingRunningNode) {
return cb(__("Swarm process is running in a separate process and cannot be started by Embark."));
}
this.startProcess((err, newProcessStarted) => {
this.addProviderToEmbarkJS();
this.addObjectToConsole();
this.events.emit("swarm:process:started", err, newProcessStarted);
cb();
});
},
stopFn: (cb) => {
if(this.usingRunningNode) {
return cb(__("Swarm process is running in a separate process and cannot be stopped by Embark."));
}
this.stopProcess(cb);
}
});
this.events.request("processes:launch", "swarm", (err, msg) => {
if (err) {
return this.logger.error(err);
}
if (msg) {
this.logger.info(msg);
}
});
}
addObjectToConsole() {
if (this.addedToConsole) return;
this.addedToConsole = true;
this.events.emit("runcode:register", "swarm", this.swarm);
}
setServiceCheck() {
if (this.isServiceRegistered) return;
this.isServiceRegistered = true;
let self = this;
this.events.on('check:backOnline:Swarm', function () {
@ -89,6 +120,8 @@ class Swarm {
}
addProviderToEmbarkJS() {
if(this.addedToEmbarkJs) return;
this.addedToEmbarkJs = true;
let code = "";
code += "\nconst __embarkSwarm = require('embarkjs-swarm')";
code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm);";
@ -99,12 +132,14 @@ class Swarm {
startProcess(callback) {
this.swarm.isAvailable((err, isAvailable) => {
if (!err || isAvailable) {
this.usingRunningNode = true;
this.logger.info("Swarm node found, using currently running node");
return callback(null, false);
}
this.logger.info("Swarm node not found, attempting to start own node");
let self = this;
const storageProcessesLauncher = new StorageProcessesLauncher({
if(this.storageProcessesLauncher === null) {
this.storageProcessesLauncher = new StorageProcessesLauncher({
logger: self.logger,
events: self.events,
storageConfig: self.storageConfig,
@ -113,13 +148,19 @@ class Swarm {
blockchainConfig: self.blockchainConfig,
embark: self.embark
});
}
self.logger.trace(`Storage module: Launching swarm process...`);
return storageProcessesLauncher.launchProcess('swarm', (err) => {
return this.storageProcessesLauncher.launchProcess('swarm', (err) => {
callback(err, true);
});
});
}
stopProcess(cb) {
if(!this.storageProcessesLauncher) return cb();
this.storageProcessesLauncher.stopProcess("swarm", cb);
}
registerUploadCommand() {
const self = this;
this.embark.registerUploadCommand('swarm', (cb) => {

View File

@ -78,6 +78,7 @@ class SwarmProcess extends ProcessWrapper {
kill() {
if (this.child) {
this.child.kill();
swarmProcess.send({result: constants.storage.exit});
}
}
}

View File

@ -1,4 +1,3 @@
/*global web3 */
let __embarkSwarm = {_swarmConnection: undefined};
let SwarmAPI = require('swarm-api');
if (SwarmAPI.default) {
@ -14,11 +13,15 @@ __embarkSwarm.setProvider = function (options) {
this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`);
return new Promise((resolve, reject) => {
if(!options.web3) {
reject(__("A web3 object must be passed in to __embarkSwarm.setProvider"));
}
const {web3, useOnlyGivenProvider} = options;
try {
if (!web3.bzz.currentProvider && !options.useOnlyGivenProvider) {
if (!web3.bzz.currentProvider && !useOnlyGivenProvider) {
this._swarmConnection = new SwarmAPI({gateway: this._connectUrl});
}
else if (options.useOnlyGivenProvider && web3.bzz.givenProvider !== null) {
else if (useOnlyGivenProvider && web3.bzz.givenProvider !== null) {
this._swarmConnection = new SwarmAPI({gateway: web3.bzz.givenProvider});
}
resolve(this);

View File

@ -72,11 +72,12 @@ Storage.isAvailable = function () {
};
// TODO: most of this logic should move to the provider implementations themselves
Storage.setProviders = function (dappConnOptions) {
Storage.setProviders = function (dappConnOptions, addlOpts) {
const self = this;
detectSeries(dappConnOptions, (dappConn, callback) => {
let options = dappConn;
if (dappConn === '$BZZ') options = {"useOnlyGivenProvider": true};
options = {...options, ...addlOpts};
try {
self.setProvider(dappConn === '$BZZ' ? dappConn : dappConn.provider, options).then(() => {
self.isAvailable().then((isAvailable) => {