From 74821073747b00cbe463ee360b8e38850aa9a40c Mon Sep 17 00:00:00 2001 From: emizzle Date: Wed, 11 Sep 2019 12:25:33 +1000 Subject: [PATCH] refactor(@embark/blockchain): Move check for blockchain started The blockchain module should not contain any ethereum-specific code, and currently it contains a check to see if the blockchain has already been started. This PR moves this check to blockchain client (ie geth or parity). This check function is registered along with the started callback. style(@embark/stack/blockchain): add missing semicolon --- packages/plugins/geth/src/index.js | 31 +++++++--- packages/plugins/parity/src/index.js | 68 ++++++++++---------- packages/stack/blockchain/src/index.js | 86 ++++++++++++-------------- 3 files changed, 98 insertions(+), 87 deletions(-) diff --git a/packages/plugins/geth/src/index.js b/packages/plugins/geth/src/index.js index f192e99e5..46894ad1f 100644 --- a/packages/plugins/geth/src/index.js +++ b/packages/plugins/geth/src/index.js @@ -1,8 +1,8 @@ import { __ } from 'embark-i18n'; -const {normalizeInput} = require('embark-utils'); -import {BlockchainProcessLauncher} from './blockchainProcessLauncher'; -import {BlockchainClient} from './blockchain'; -import {ws, rpc} from './check.js'; +const { normalizeInput } = require('embark-utils'); +import { BlockchainProcessLauncher } from './blockchainProcessLauncher'; +import { BlockchainClient } from './blockchain'; +import { ws, rpc } from './check.js'; const constants = require('embark-core/constants'); class Geth { @@ -23,6 +23,11 @@ class Geth { } this.events.request("blockchain:node:register", constants.blockchain.clients.geth, { + isStartedFn: (isStartedCb) => { + this._doCheck((state) => { + return isStartedCb(null, state.status === "on"); + }); + }, launchFn: (readyCb) => { this.events.request('processes:register', 'blockchain', { launchFn: (cb) => { @@ -73,22 +78,30 @@ class Geth { } _getNodeState(err, version, cb) { - if (err) return cb({name: "Ethereum node not found", status: 'off'}); + if (err) return cb({ name: "Ethereum node not found", status: 'off' }); let nodeName = "go-ethereum"; let versionNumber = version.split("-")[0]; let name = nodeName + " " + versionNumber + " (Ethereum)"; - return cb({name, status: 'on'}); + return cb({ name, status: 'on' }); + } + + _doCheck(cb) { + const { rpcHost, rpcPort, wsRPC, wsHost, wsPort } = this.blockchainConfig; + if (wsRPC) { + return ws(wsHost, wsPort, (err, version) => this._getNodeState(err, version, cb)); + } + rpc(rpcHost, rpcPort, (err, version) => this._getNodeState(err, version, cb)); } // TODO: need to get correct port taking into account the proxy registerServiceCheck() { this.events.request("services:register", 'Ethereum', (cb) => { - const {rpcHost, rpcPort, wsRPC, wsHost, wsPort} = this.blockchainConfig; + const { rpcHost, rpcPort, wsRPC, wsHost, wsPort } = this.blockchainConfig; if (wsRPC) { - return ws(wsHost, wsPort + 10, (err, version) => this._getNodeState(err, version, cb)); + return ws(wsHost, wsPort, (err, version) => this._getNodeState(err, version, cb)); } - rpc(rpcHost, rpcPort + 10, (err, version) => this._getNodeState(err, version, cb)); + rpc(rpcHost, rpcPort, (err, version) => this._getNodeState(err, version, cb)); }, 5000, 'off'); } diff --git a/packages/plugins/parity/src/index.js b/packages/plugins/parity/src/index.js index fa02c1eef..71db9cf9c 100644 --- a/packages/plugins/parity/src/index.js +++ b/packages/plugins/parity/src/index.js @@ -24,29 +24,33 @@ class Parity { } this.events.request("blockchain:node:register", constants.blockchain.clients.parity, { + isStartedFn: (isStartedCb) => { + this._doCheck((state) => { + return isStartedCb(null, state.status === "on"); + }); + }, launchFn: (readyCb) => { - this.events.request('processes:register', 'blockchain', { - launchFn: (cb) => { - // this.startBlockchainNode(readyCb); - this.startBlockchainNode(cb); - }, - stopFn: (cb) => { - this.stopBlockchainNode(cb); - } - }); - this.events.request("processes:launch", "blockchain", (err) => { - if (err) { - this.logger.error(`Error launching blockchain process: ${err.message || err}`); - } - readyCb(); - }); - this.registerServiceCheck(); - }, - stopFn: async (cb) => { - await this.events.request("processes:stop", "blockchain"); - cb(); - } - }); + this.events.request('processes:register', 'blockchain', { + launchFn: (cb) => { + this.startBlockchainNode(cb); + }, + stopFn: (cb) => { + this.stopBlockchainNode(cb); + } + }); + this.events.request("processes:launch", "blockchain", (err) => { + if (err) { + this.logger.error(`Error launching blockchain process: ${err.message || err}`); + } + readyCb(); + }); + this.registerServiceCheck(); + }, + stopFn: async (cb) => { + await this.events.request("processes:stop", "blockchain"); + cb(); + } + }); } shouldInit() { @@ -57,23 +61,25 @@ class Parity { } _getNodeState(err, version, cb) { - if (err) return cb({name: "Ethereum node not found", status: 'off'}); + if (err) return cb({ name: "Ethereum node not found", status: 'off' }); let nodeName = "parity"; let versionNumber = version.split("-")[0]; let name = nodeName + " " + versionNumber + " (Ethereum)"; - return cb({name, status: 'on'}); + return cb({ name, status: 'on' }); + } + + _doCheck(cb) { + const { rpcHost, rpcPort, wsRPC, wsHost, wsPort } = this.blockchainConfig; + if (wsRPC) { + return ws(wsHost, wsPort, (err, version) => this._getNodeState(err, version, cb)); + } + rpc(rpcHost, rpcPort, (err, version) => this._getNodeState(err, version, cb)); } // TODO: need to get correct port taking into account the proxy registerServiceCheck() { - this.events.request("services:register", 'Ethereum', (cb) => { - const {rpcHost, rpcPort, wsRPC, wsHost, wsPort} = this.blockchainConfig; - if (wsRPC) { - return ws(wsHost, wsPort, (err, version) => this._getNodeState(err, version, cb)); - } - rpc(rpcHost, rpcPort, (err, version) => this._getNodeState(err, version, cb)); - }, 5000, 'off'); + this.events.request("services:register", 'Ethereum', this._doCheck.bind(this), 5000, 'off'); } startBlockchainNode(callback) { diff --git a/packages/stack/blockchain/src/index.js b/packages/stack/blockchain/src/index.js index d042689cd..179d5db48 100644 --- a/packages/stack/blockchain/src/index.js +++ b/packages/stack/blockchain/src/index.js @@ -1,7 +1,6 @@ import async from 'async'; -const {__} = require('embark-i18n'); +const { __ } = require('embark-i18n'); const constants = require('embark-core/constants'); -const Web3RequestManager = require('web3-core-requestmanager'); import BlockchainAPI from "./api"; class Blockchain { @@ -22,57 +21,50 @@ class Blockchain { embark.registerActionForEvent("pipeline:generateAll:before", this.addArtifactFile.bind(this)); this.blockchainNodes = {}; - this.events.setCommandHandler("blockchain:node:register", (clientName, startCb) => { - this.blockchainNodes[clientName] = startCb; + this.events.setCommandHandler("blockchain:node:register", (clientName, { isStartedFn, launchFn, stopFn }) => { + + if (!isStartedFn) { + throw new Error(`Blockchain client '${clientName}' must be registered with an 'isStarted' function, client not registered.`); + } + if (!launchFn) { + throw new Error(`Blockchain client '${clientName}' must be registered with a 'launchFn' function, client not registered.`); + } + if (!stopFn) { + throw new Error(`Blockchain client '${clientName}' must be registered with a 'stopFn' function, client not registered.`); + } + + this.blockchainNodes[clientName] = { isStartedFn, launchFn, stopFn }; }); - this.events.setCommandHandler("blockchain:node:start", async (initialBlockchainConfig, cb) => { - this.plugins.emitAndRunActionsForEvent("blockchain:config:modify", initialBlockchainConfig, (err, blockchainConfig) => { + this.events.setCommandHandler("blockchain:node:start", (blockchainConfig, cb) => { + const clientName = blockchainConfig.client; + const started = () => { + this.startedClient = clientName; + this.events.emit("blockchain:started", clientName); + }; + if (clientName === constants.blockchain.vm) { + started(); + return cb(); + } + + const client = this.blockchainNodes[clientName]; + + if (!client) return cb(`Blockchain client '${clientName}' not found, please register this node using 'blockchain:node:register'.`); + + // check if we should should start + client.isStartedFn.call(client, (err, isStarted) => { if (err) { - this.logger.error(__('Error getting modified blockchain config: %s', err.message || err)); - blockchainConfig = initialBlockchainConfig; + return cb(err); } - const self = this; - const clientName = blockchainConfig.client; - function started() { - self.startedClient = clientName; - self.events.emit("blockchain:started", clientName); - } - if (clientName === constants.blockchain.vm) { + if (isStarted) { + // Node may already be started started(); - return cb(); + return cb(null, true); } - const requestManager = new Web3RequestManager.Manager(blockchainConfig.endpoint); - - const ogConsoleError = console.error; - // TODO remove this once we update to web3 2.0 - // TODO in web3 1.0, it console.errors "connection not open on send()" even if we catch the error - console.error = (...args) => { - if (args[0].indexOf('connection not open on send()') > -1) { - return; - } - ogConsoleError(...args); - }; - requestManager.send({method: 'eth_accounts'}, (err, _accounts) => { - console.error = ogConsoleError; - if (!err) { - // Node is already started - started(); - return cb(null, true); - } - const clientFunctions = this.blockchainNodes[clientName]; - if (!clientFunctions) { - return cb(__("Client %s not found in registered plugins", clientName)); - } - - let onStart = () => { - started(); - cb(); - }; - - this.startedClient = clientName; - clientFunctions.launchFn.apply(clientFunctions, [onStart]); - + // start node + client.launchFn.call(client, () => { + started(); + cb(); }); }); });