From 51b82243258f39a904028eda961d1c762a6426af Mon Sep 17 00:00:00 2001 From: Anthony Laibe Date: Mon, 12 Nov 2018 11:05:01 +0000 Subject: [PATCH] feat: permanently save logs/events --- src/lib/core/fs.js | 5 ++ src/lib/modules/blockchain_connector/index.js | 54 +++++++++++++++---- src/lib/modules/console_listener/index.js | 49 ++++++++++++++--- 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/lib/core/fs.js b/src/lib/core/fs.js index 2f2489641..27ee80edb 100644 --- a/src/lib/core/fs.js +++ b/src/lib/core/fs.js @@ -116,6 +116,10 @@ function existsSync() { return restrictPath(fs.existsSync, fs.existsSync, 1, arguments); } +function ensureFileSync() { + return restrictPath(fs.ensureFileSync, fs.ensureFileSync, 1, arguments); +} + function access() { return restrictPath(fs.access, fs.access, 1, arguments); } @@ -190,6 +194,7 @@ module.exports = { diagramPath, embarkPath, existsSync, + ensureFileSync, mkdirp, mkdirpSync, move, diff --git a/src/lib/modules/blockchain_connector/index.js b/src/lib/modules/blockchain_connector/index.js index 1be9c2ab4..45cf52919 100644 --- a/src/lib/modules/blockchain_connector/index.js +++ b/src/lib/modules/blockchain_connector/index.js @@ -4,6 +4,7 @@ const Provider = require('./provider.js'); const utils = require('../../utils/utils'); const constants = require('../../constants'); const embarkJsUtils = require('embarkjs').Utils; +const fs = require('../../core/fs'); const WEB3_READY = 'blockchain:ready'; @@ -24,6 +25,22 @@ class BlockchainConnector { this.wait = options.wait; this.contractsSubscriptions = []; this.contractsEvents = []; + this.logFile = fs.dappPath(".embark", "contractEvents.json"); + + this.writeLogFile = async.cargo((tasks, callback) => { + const data = this._readEvents(); + + tasks.forEach(task => { + data[new Date().getTime()] = task; + }); + + fs.writeJson(this.logFile, data, err => { + if (err) { + console.error(err); + } + callback(); + }); + }); self.events.setCommandHandler("blockchain:web3:isReady", (cb) => { cb(self.isWeb3Ready); @@ -191,19 +208,20 @@ class BlockchainConnector { } registerEvents() { - const self = this; - self.events.on('check:wentOffline:Ethereum', () => { - self.logger.warn('Ethereum went offline: stopping web3 provider...'); - self.provider.stop(); + this.events.on('check:wentOffline:Ethereum', () => { + this.logger.warn('Ethereum went offline: stopping web3 provider...'); + this.provider.stop(); // once the node goes back online, we can restart the provider - self.events.once('check:backOnline:Ethereum', () => { - self.logger.warn('Ethereum back online: starting web3 provider...'); - self.provider.startWeb3Provider(() => { - self.logger.warn('web3 provider restarted after ethereum node came back online'); + this.events.once('check:backOnline:Ethereum', () => { + this.logger.warn('Ethereum back online: starting web3 provider...'); + this.provider.startWeb3Provider(() => { + this.logger.warn('web3 provider restarted after ethereum node came back online'); }); }); }); + + this.events.on('blockchain:contracts:event', this._saveEvent.bind(this)); } onReady(callback) { @@ -404,7 +422,7 @@ class BlockchainConnector { 'get', '/embark-api/blockchain/contracts/events', (_req, res) => { - res.send(JSON.stringify(this.contractsEvents)); + res.send(JSON.stringify(this._getEvents())); } ); @@ -699,6 +717,24 @@ class BlockchainConnector { callback(); }); } + + _getEvents() { + const data = this._readEvents(); + return Object.values(data).reverse(); + } + + _saveEvent(event) { + this.writeLogFile.push(event); + } + + _readEvents() { + fs.ensureFileSync(this.logFile); + try { + return JSON.parse(fs.readFileSync(this.logFile)); + } catch(_error) { + return {}; + } + } } BlockchainConnector.ACCEPTED_TYPES = ['rpc', 'ws', 'vm']; diff --git a/src/lib/modules/console_listener/index.js b/src/lib/modules/console_listener/index.js index e778c8cab..274774701 100644 --- a/src/lib/modules/console_listener/index.js +++ b/src/lib/modules/console_listener/index.js @@ -1,4 +1,6 @@ +const async = require('async'); const utils = require('../../utils/utils.js'); +const fs = require('../../core/fs'); class ConsoleListener { constructor(embark, options) { @@ -7,20 +9,37 @@ class ConsoleListener { this.ipc = options.ipc; this.events = embark.events; this.addressToContract = []; - this.logs = []; this.contractsConfig = embark.config.contractsConfig; this.contractsDeployed = false; this.outputDone = false; + this.logFile = fs.dappPath(".embark", "contractLogs.json"); + this._listenForLogRequests(); + this._registerAPI(); + + this.events.on("contracts:log", this._saveLog.bind(this)); this.events.on('outputDone', () => { this.outputDone = true; }); - this._registerAPI(); - this.events.on("contractsDeployed", () => { this.contractsDeployed = true; this._updateContractList(); }); + + this.writeLogFile = async.cargo((tasks, callback) => { + const data = this._readLogs(); + + tasks.forEach(task => { + data[new Date().getTime()] = task; + }); + + fs.writeJson(this.logFile, data, err => { + if (err) { + console.error(err); + } + callback(); + }); + }); } _updateContractList() { @@ -97,8 +116,8 @@ class ConsoleListener { gasUsed = utils.hexToNumber(gasUsed); blockNumber = utils.hexToNumber(blockNumber); - this.logs.push(Object.assign({}, request, {name, functionName, paramString, gasUsed, blockNumber})); - this.events.emit('contracts:log', this.logs[this.logs.length - 1]); + const log = Object.assign({}, request, {name, functionName, paramString, gasUsed, blockNumber}); + this.events.emit('contracts:log', log); this.logger.info(`Blockchain>`.underline + ` ${name}.${functionName}(${paramString})`.bold + ` | ${transactionHash} | gas:${gasUsed} | blk:${blockNumber} | status:${status}`); this.events.emit('blockchain:tx', { name: name, functionName: functionName, paramString: paramString, transactionHash: transactionHash, gasUsed: gasUsed, blockNumber: blockNumber, status: status }); @@ -121,10 +140,28 @@ class ConsoleListener { 'get', apiRoute, (req, res) => { - res.send(JSON.stringify(this.logs)); + res.send(JSON.stringify(this._getLogs())); } ); } + + _getLogs() { + const data = this._readLogs(); + return Object.values(data).reverse(); + } + + _saveLog(log) { + this.writeLogFile.push(log); + } + + _readLogs() { + fs.ensureFileSync(this.logFile); + try { + return JSON.parse(fs.readFileSync(this.logFile)); + } catch(_error) { + return {}; + } + } } module.exports = ConsoleListener;