fix(@embark/storage): Storage processes race conditions

Previously, storage providers in embarkjs were not waiting for their respective storage process (ipfs and swarm) to start before running `registerProvider` and `setProvider` in the console.

This PR forces the `registerProvider` and `setProviders` from running in the console until the storage processes have loaded. As a side effect, the code generation of `EmbarkJS` must wait for the storage module ot be fully initiated (ie once the processes have launched and the `registerProvider` and `setProviders` have been run) before generating the code.

This fixes errors pertaining to `Could not connect to a storage provider using any of the dappConnections in the storage config` as these errors were typically caused by `setProviders` being called before the storage processes had fully launched.
This commit is contained in:
emizzle 2019-03-13 08:58:44 +11:00 committed by Iuri Matias
parent be3817821d
commit 6f5efb16a6
5 changed files with 46 additions and 23 deletions

View File

@ -192,9 +192,11 @@ class Engine {
this.registerModule('code_generator', {plugins: self.plugins, env: self.env});
const generateCode = function (modifiedAssets) {
self.events.request("module:storage:initiated", () => {
self.events.request("code-generator:embarkjs:build", () => {
self.events.emit('code-generator-ready', modifiedAssets);
});
});
};
const cargo = async.cargo((tasks, callback) => {
const modifiedAssets = tasks.map(task => task.modifiedAsset).filter(asset => asset); // filter null elements
@ -271,9 +273,27 @@ class Engine {
}
storageService(_options) {
this.registerModule('storage', {plugins: this.plugins});
async.parallel([
(next) => {
if (!this.config.storageConfig.available_providers.includes("ipfs")) {
return next();
}
this.registerModule('ipfs');
this.events.on("ipfs:process:started", next);
},
(next) => {
if (!this.config.storageConfig.available_providers.includes("swarm")) {
return next();
}
this.registerModule('swarm');
this.events.on("swarm:process:started", next);
}
], (err) => {
if(err) {
console.error(__("Error starting storage process(es): %s", err));
}
this.registerModule('storage', {plugins: this.plugins});
});
}
web3Service(options) {

View File

@ -8,7 +8,6 @@ const constants = require('../../constants.json');
class IPFS {
constructor(embark, options) {
const self = this;
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
@ -26,9 +25,10 @@ class IPFS {
this.registerUploadCommand();
this.events.request("processes:register", "ipfs", (cb) => {
self.startProcess(() => {
this.startProcess(() => {
this.addStorageProviderToEmbarkJS();
this.addObjectToConsole();
this.events.emit("ipfs:process:started");
cb();
});
});
@ -37,7 +37,7 @@ class IPFS {
if (!err) {
return;
}
self.logger.info("IPFS node not found, attempting to start own node");
this.logger.info("IPFS node not found, attempting to start own node");
this.listenToCommands();
this.registerConsoleCommands();
this.events.request('processes:launch', 'ipfs');

View File

@ -7,7 +7,9 @@ class Storage {
if (!this.storageConfig.enabled) return;
this.handleUploadCommand();
this.addSetProviders();
this.addSetProviders(() => {
this.embark.events.setCommandHandler("module:storage:initiated", (cb) => { cb(); });
});
}
handleUploadCommand() {
@ -26,7 +28,7 @@ class Storage {
});
}
addSetProviders() {
addSetProviders(cb) {
let code = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.storageConfig.dappConnection || [])});`;
let shouldInit = (storageConfig) => {
@ -36,6 +38,7 @@ class Storage {
this.embark.addProviderInit('storage', code, shouldInit);
this.embark.events.request("runcode:storage:providerRegistered", () => {
this.embark.addConsoleProviderInit('storage', code, shouldInit);
cb();
});
}

View File

@ -46,12 +46,9 @@ class Swarm {
this.swarm = new SwarmAPI({gateway: this.providerUrl});
this.setServiceCheck();
this.addProviderToEmbarkJS();
this.addObjectToConsole();
this.registerUploadCommand();
// swarm needs geth to be running first
this.events.once(constants.blockchain.blockchainReady, () => {
this.swarm.isAvailable((err, isAvailable) => {
if (!err || isAvailable) {
this.logger.info("Swarm node found, using currently running node");
@ -60,7 +57,10 @@ class Swarm {
this.logger.info("SWARM: Swarm node not found, attempting to start own node");
this.listenToCommands();
this.registerConsoleCommands();
return this.startProcess(() => {});
return this.startProcess(() => {
this.addProviderToEmbarkJS();
this.addObjectToConsole();
this.events.emit("swarm:process:started");
});
});
}

View File

@ -62,7 +62,7 @@ class SwarmProcess extends ProcessWrapper {
// Swarm logs appear in stderr somehow
this.child.stderr.on('data', (data) => {
data = data.toString();
if (!self.readyCalled && data.indexOf('Swarm http proxy started') > -1) {
if (!self.readyCalled && (data.includes('Swarm http proxy started') || data.includes('Swarm network started'))) {
self.readyCalled = true;
self.send({result: constants.storage.initiated});
}