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 ) {
2018-07-07 15:11:45 +00:00
const self = this ;
2018-06-01 03:12:17 +00:00
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-07-07 15:11:45 +00:00
embark . events . setCommandHandler ( 'storage:upload' , ( cb ) => {
let platform = options . storageConfig . upload . provider ;
if ( [ 'swarm' , 'ipfs' ] . indexOf ( platform ) === - 1 ) {
return cb ( { message : _ _ ( 'platform "{{platform}}" is specified as the upload provider, however no plugins have registered an upload command for "{{platform}}".' , { platform : platform } ) } ) ;
}
} ) ;
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 ;