2018-05-28 12:59:18 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
const utils = require('../../utils/utils.js');
|
|
|
|
const fs = require('../../core/fs.js');
|
|
|
|
const _ = require('underscore');
|
|
|
|
const async = require('async');
|
|
|
|
const StorageProcessesLauncher = require('../../processes/storageProcesses/storageProcessesLauncher');
|
|
|
|
const constants = require('../../constants');
|
2018-05-28 12:59:18 +00:00
|
|
|
|
|
|
|
class Storage {
|
2018-06-01 03:12:17 +00:00
|
|
|
constructor(embark, options){
|
|
|
|
this._embark = embark;
|
|
|
|
this._options = options;
|
|
|
|
this._storageConfig = options.storageConfig;
|
|
|
|
this._webServerConfig = options.webServerConfig;
|
|
|
|
this._blockchainConfig = options.blockchainConfig;
|
|
|
|
this._servicesMonitor = options.servicesMonitor;
|
|
|
|
this._events = options.events;
|
|
|
|
this._logger = options.logger;
|
2018-05-30 06:34:36 +00:00
|
|
|
|
2018-06-26 04:18:55 +00:00
|
|
|
if(!this._storageConfig.enabled) return;
|
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
// filter list of dapp connections based on available_providers set in config
|
|
|
|
let hasSwarm = _.contains(this._storageConfig.available_providers, 'swarm'); // don't need to eval this in every loop iteration
|
|
|
|
// contains valid dapp storage providers
|
|
|
|
this._validDappProviders = _.filter(this._storageConfig.dappConnection, (conn) => {
|
|
|
|
return _.contains(this._storageConfig.available_providers, conn.provider) || (conn === '$BZZ' && hasSwarm);
|
|
|
|
});
|
2018-05-30 06:34:36 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
this.initStorageForEmbark();
|
|
|
|
this.initStorageForDapp();
|
2018-05-28 12:59:18 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
// don't start storage processes on build command, only on upload or run
|
|
|
|
if(_.contains(options.context, constants.contexts.upload) || _.contains(options.context, constants.contexts.run)){
|
|
|
|
this.startStorageProcesses();
|
2018-05-30 06:34:36 +00:00
|
|
|
}
|
2018-06-01 03:12:17 +00:00
|
|
|
}
|
2018-05-30 06:34:36 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
_checkStorageEndpoint(platform, callback) {
|
|
|
|
let checkFn;
|
|
|
|
let self = this;
|
|
|
|
self._logger.trace(`Storage module: Checking ${platform} availability...`);
|
|
|
|
_.find(self._servicesMonitor.checkList, (value, key) => {
|
|
|
|
if(key.toLowerCase() === platform.toLowerCase()){
|
|
|
|
checkFn = value;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!checkFn || typeof checkFn.fn !== 'function') {
|
|
|
|
self._logger.trace(`Storage module: Check for ${platform} node does not exist.`);
|
|
|
|
return callback();
|
|
|
|
}
|
2018-05-28 12:59:18 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
checkFn.fn(function (serviceCheckResult) {
|
|
|
|
if (!serviceCheckResult.status || serviceCheckResult.status === 'off') {
|
|
|
|
self._logger.trace(`Storage module: ${platform} node not available.`);
|
|
|
|
return callback('No node');
|
|
|
|
}
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
2018-05-28 12:59:18 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
_startStorageNode(platform, callback) {
|
|
|
|
let self = this;
|
|
|
|
const storageProcessesLauncher = new StorageProcessesLauncher({
|
|
|
|
logger: self._logger,
|
|
|
|
events: self._events,
|
|
|
|
storageConfig: self._storageConfig,
|
|
|
|
webServerConfig: self._webServerConfig,
|
|
|
|
blockchainConfig: self._blockchainConfig
|
|
|
|
});
|
|
|
|
self._logger.trace(`Storage module: Launching ${platform} process...`);
|
|
|
|
return storageProcessesLauncher.launchProcess(platform.toLowerCase(), (err) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
2018-05-30 06:34:36 +00:00
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
/// Initializes a storage provider for Embark upload
|
|
|
|
initStorageForEmbark(){
|
|
|
|
let storageProviderCls = require(`../${this._storageConfig.upload.provider}/index.js`);
|
|
|
|
let uploadProvider = new storageProviderCls(this._embark, this._options); /*eslint no-new: "off"*/
|
|
|
|
|
|
|
|
if(typeof uploadProvider.commandlineDeploy == 'function') uploadProvider.commandlineDeploy();
|
|
|
|
if(typeof uploadProvider.setServiceCheck == 'function') uploadProvider.setServiceCheck();
|
|
|
|
if(typeof uploadProvider.addObjectToConsole == 'function') uploadProvider.addObjectToConsole();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes a storage provider for EmbarkJS
|
|
|
|
*
|
|
|
|
* @return {void}
|
|
|
|
*/
|
|
|
|
initStorageForDapp(){
|
|
|
|
// now we need to add instantiate any dappConnection/available_providers storage providers to add
|
|
|
|
// their provider code to embarkjs
|
|
|
|
this._validDappProviders.forEach(dappConn => {
|
|
|
|
if(!dappConn.provider) return;
|
|
|
|
let storageProviderCls = require(`../${dappConn.provider}/index.js`);
|
|
|
|
|
|
|
|
// override options with dappConnection settings
|
|
|
|
let storageOptions = this._options;
|
|
|
|
storageOptions.protocol = dappConn.protocol;
|
|
|
|
storageOptions.host = dappConn.host;
|
|
|
|
storageOptions.port = dappConn.port;
|
|
|
|
|
|
|
|
// then instantiate the storage provdier class
|
|
|
|
let storageProvider = new storageProviderCls(this._embark, storageOptions); /*eslint no-new: "off"*/
|
|
|
|
|
|
|
|
// register the service check so we can use it to check if the process is running before spawning it
|
|
|
|
// check that it hasn't already been done above
|
|
|
|
if(dappConn.provider !== this._storageConfig.upload.provider){
|
|
|
|
if(typeof storageProvider.setServiceCheck == 'function') storageProvider.setServiceCheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
// add __embarkSwarm and __embarkIPFS objects to EmbarkJS
|
|
|
|
if(typeof storageProvider.addProviderToEmbarkJS == 'function') storageProvider.addProviderToEmbarkJS();
|
|
|
|
});
|
|
|
|
|
|
|
|
// add the storage provider code (__embarkStorage) to embarkjs
|
|
|
|
this.addProviderToEmbarkJS();
|
|
|
|
|
|
|
|
// add the code to call setProviders in embarkjs after embark is ready
|
|
|
|
this.addSetProviders();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the storage provider code (__embarkStorage) to embarkjs
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
addProviderToEmbarkJS(){
|
|
|
|
// TODO: make this a shouldAdd condition
|
|
|
|
if (this._storageConfig === {} || !this._storageConfig.dappConnection || !this._storageConfig.dappConnection.length) {
|
|
|
|
return;
|
2018-05-28 12:59:18 +00:00
|
|
|
}
|
2018-06-01 03:12:17 +00:00
|
|
|
|
|
|
|
let code = "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
|
|
|
|
|
|
|
|
this._embark.addCodeToEmbarkJS(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the code to call setProviders in embarkjs after embark is ready
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
addSetProviders() {
|
|
|
|
|
|
|
|
let code = `\n__embarkStorage.setProviders(${JSON.stringify(this._validDappProviders)});`;
|
|
|
|
let shouldInit = (storageConfig) => {
|
|
|
|
return (this._validDappProviders !== undefined && this._validDappProviders.length > 0 && storageConfig.enabled === true);
|
|
|
|
};
|
|
|
|
|
|
|
|
this._embark.addProviderInit('storage', code, shouldInit);
|
|
|
|
}
|
|
|
|
|
2018-06-01 16:53:23 +00:00
|
|
|
checkStorageService(platform, url, callback) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
// start the upload storage node
|
|
|
|
self._checkStorageEndpoint(platform, function (err) {
|
|
|
|
if (!err) {
|
2018-06-15 06:35:05 +00:00
|
|
|
return callback(null);
|
2018-06-01 16:53:23 +00:00
|
|
|
}
|
|
|
|
self._startStorageNode(platform, (err) => {
|
|
|
|
if (err) {
|
2018-06-15 06:35:05 +00:00
|
|
|
return callback(err);
|
2018-06-01 16:53:23 +00:00
|
|
|
}
|
|
|
|
// Check endpoint again to see if really did start
|
|
|
|
self._checkStorageEndpoint(platform, (err) => {
|
|
|
|
if (err) {
|
2018-06-15 06:35:05 +00:00
|
|
|
return callback(err);
|
2018-06-01 16:53:23 +00:00
|
|
|
}
|
2018-06-15 06:35:05 +00:00
|
|
|
callback(null);
|
2018-06-01 16:53:23 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
startStorageProcesses(){
|
|
|
|
let platform = this._storageConfig.upload.provider;
|
|
|
|
let self = this;
|
2018-06-15 06:35:05 +00:00
|
|
|
let withErrors = false;
|
2018-06-01 03:12:17 +00:00
|
|
|
|
|
|
|
async.waterfall([
|
2018-06-01 16:53:23 +00:00
|
|
|
function _checkStorageService(callback){
|
2018-06-15 06:35:05 +00:00
|
|
|
self.checkStorageService(platform, utils.buildUrlFromConfig(self._storageConfig.upload), (err) => {
|
|
|
|
// log error and continue
|
|
|
|
if(err){
|
|
|
|
self._logger.error(err);
|
|
|
|
withErrors = true;
|
|
|
|
}
|
|
|
|
callback(null);
|
|
|
|
});
|
2018-06-01 03:12:17 +00:00
|
|
|
},
|
|
|
|
function checkDappConnectionStorageService(callback){
|
|
|
|
// start any dappConnection storage nodes
|
2018-06-15 06:35:05 +00:00
|
|
|
async.each(self._validDappProviders, function(dappConn, cb) {
|
|
|
|
if(!dappConn.provider || dappConn.provider === platform) {
|
|
|
|
return cb(null);
|
|
|
|
} // don't start the process we've just started above
|
|
|
|
|
|
|
|
self.checkStorageService(dappConn.provider, utils.buildUrlFromConfig(dappConn), (err) => {
|
|
|
|
// log error and continue
|
|
|
|
if(err){
|
|
|
|
self._logger.error(err);
|
|
|
|
withErrors = true;
|
|
|
|
}
|
|
|
|
cb(null);
|
|
|
|
});
|
|
|
|
}, callback);
|
|
|
|
}
|
|
|
|
], function (){
|
|
|
|
let strComplete = __('Finished starting all storage providers');
|
|
|
|
if(withErrors){
|
|
|
|
strComplete += ', ' + __('with errors.');
|
|
|
|
return self._logger.warn(strComplete);
|
2018-06-01 03:12:17 +00:00
|
|
|
}
|
2018-06-15 06:35:05 +00:00
|
|
|
self._logger.info(strComplete + '.');
|
|
|
|
});
|
2018-06-01 03:12:17 +00:00
|
|
|
}
|
2018-05-28 12:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Storage;
|