conflict in actions and saga

This commit is contained in:
Jonathan Rainville 2018-08-02 12:48:41 -04:00 committed by Iuri Matias
parent 3f62ebc2f7
commit 7c4b83591b
7 changed files with 110 additions and 18 deletions

View File

@ -6,6 +6,10 @@ export const RECEIVE_ACCOUNTS_ERROR = 'RECEIVE_ACCOUNTS_ERROR';
export const FETCH_PROCESSES = 'FETCH_PROCESSES'; export const FETCH_PROCESSES = 'FETCH_PROCESSES';
export const RECEIVE_PROCESSES = 'RECEIVE_PROCESSES'; export const RECEIVE_PROCESSES = 'RECEIVE_PROCESSES';
export const RECEIVE_PROCESSES_ERROR = 'RECEIVE_PROCESSES_ERROR'; export const RECEIVE_PROCESSES_ERROR = 'RECEIVE_PROCESSES_ERROR';
// Process logs
export const FETCH_PROCESS_LOGS = 'FETCH_PROCESS_LOGS';
export const RECEIVE_PROCESS_LOGS = 'RECEIVE_PROCESS_LOGS';
export const RECEIVE_PROCESS_LOGS_ERROR = 'RECEIVE_PROCESS_LOGS_ERROR';
// Blocks // Blocks
export const FETCH_BLOCKS = 'FETCH_BLOCKS'; export const FETCH_BLOCKS = 'FETCH_BLOCKS';
export const RECEIVE_BLOCKS = 'RECEIVE_BLOCKS'; export const RECEIVE_BLOCKS = 'RECEIVE_BLOCKS';
@ -47,9 +51,32 @@ export function receiveProcesses(processes) {
}; };
} }
export function receiveProcessesError() { export function receiveProcessesError(error) {
return { return {
type: RECEIVE_PROCESSES_ERROR type: RECEIVE_PROCESSES_ERROR,
error
};
}
export function fetchProcessLogs(processName) {
return {
type: FETCH_PROCESS_LOGS,
processName
};
}
export function receiveProcessLogs(processName, logs) {
return {
type: RECEIVE_PROCESS_LOGS,
processName,
logs
};
}
export function receiveProcessLogsError(error) {
return {
type: RECEIVE_PROCESS_LOGS_ERROR,
error
}; };
} }

View File

@ -4,7 +4,7 @@ import constants from '../constants';
const BASE_URL = 'http://localhost:8000/embark-api'; const BASE_URL = 'http://localhost:8000/embark-api';
export function fetchAccounts() { export function fetchAccounts() {
return axios.get(constants.httpEndpoint + 'blockchain/accounts'); return axios.get(constants.httpEndpoint + '/blockchain/accounts');
} }
export function fetchBlocks(from) { export function fetchBlocks(from) {
@ -16,5 +16,9 @@ export function fetchTransactions(blockFrom) {
} }
export function fetchProcesses() { export function fetchProcesses() {
return axios.get(constants.httpEndpoint + 'processes'); return axios.get(constants.httpEndpoint + '/processes');
}
export function fetchProcessLogs(processName) {
return axios.get(`${constants.httpEndpoint}/process-logs/${processName}`);
} }

View File

@ -1,5 +1,6 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Tab} from "tabler-react"; import connect from "react-redux/es/connect/connect";
import {fetchProcessLogs} from "../actions";
import constants from '../constants'; import constants from '../constants';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -9,11 +10,15 @@ class Process extends Component {
this.state = { this.state = {
logs: [] logs: []
}; };
this.gotOriginalLogs = false;
} }
componentDidMount() { componentDidMount() {
const self = this; const self = this;
this.ws = new WebSocket(constants.wsEndpoint + 'process-logs/' + self.props.processName);
this.props.fetchProcessLogs(self.props.processName);
this.ws = new WebSocket(constants.wsEndpoint + '/process-logs/' + self.props.processName);
this.ws.onmessage = function(evt) { this.ws.onmessage = function(evt) {
const log = JSON.parse(evt.data); const log = JSON.parse(evt.data);
@ -33,6 +38,17 @@ class Process extends Component {
}; };
} }
shouldComponentUpdate(nextProps, _nextState) {
if (!this.gotOriginalLogs && nextProps.logs && nextProps.logs[this.props.processName]) {
const logs = nextProps.logs[this.props.processName].concat(this.state.logs);
this.gotOriginalLogs = true;
this.setState({
logs
});
}
return true;
}
componentWillUnmount() { componentWillUnmount() {
this.ws.close(); this.ws.close();
this.ws = null; this.ws = null;
@ -44,7 +60,7 @@ class Process extends Component {
State: {this.props.state} State: {this.props.state}
<div className="logs"> <div className="logs">
{ {
this.state.logs.map((item, i) => <p key={i} className={item.logLevel}>{item.msg}</p>) this.state.logs.map((item, i) => <p key={i} className={item.logLevel}>{item.msg_clear || item.msg}</p>)
} }
</div> </div>
</div>); </div>);
@ -52,8 +68,19 @@ class Process extends Component {
} }
Process.propTypes = { Process.propTypes = {
processName: PropTypes.string, processName: PropTypes.string.isRequired,
state: PropTypes.string state: PropTypes.string.isRequired,
fetchProcessLogs: PropTypes.func,
logs: PropTypes.object
}; };
export default Process; function mapStateToProps(state) {
return {logs: state.processes.logs};
}
export default connect(
mapStateToProps,
{
fetchProcessLogs
}
)(Process);

View File

@ -1,4 +1,4 @@
{ {
"httpEndpoint": "http://localhost:8000/embark-api/", "httpEndpoint": "http://localhost:8000/embark-api",
"wsEndpoint": "ws://localhost:8000/embark-api/" "wsEndpoint": "ws://localhost:8000/embark-api"
} }

View File

@ -1,11 +1,21 @@
import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR} from "../actions"; import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR, RECEIVE_PROCESS_LOGS, RECEIVE_PROCESS_LOGS_ERROR} from "../actions";
export default function processes(state = {}, action) { export default function processes(state = {}, action) {
switch (action.type) { switch (action.type) {
case RECEIVE_PROCESSES: case RECEIVE_PROCESSES:
return Object.assign({}, state, {data: action.processes.data}); return Object.assign({}, state, {data: action.processes.data});
case RECEIVE_PROCESSES_ERROR: case RECEIVE_PROCESSES_ERROR:
return Object.assign({}, state, {error: true}); return Object.assign({}, state, {error: action.error});
case RECEIVE_PROCESS_LOGS:
return {
...state,
logs: {
...state.logs,
[action.processName]: action.logs.data
}
};
case RECEIVE_PROCESS_LOGS_ERROR:
return Object.assign({}, state, {error: action.error});
default: default:
return state; return state;
} }

View File

@ -46,7 +46,7 @@ export function *fetchProcesses() {
const processes = yield call(api.fetchProcesses); const processes = yield call(api.fetchProcesses);
yield put(actions.receiveProcesses(processes)); yield put(actions.receiveProcesses(processes));
} catch (e) { } catch (e) {
yield put(actions.receiveProcessesError()); yield put(actions.receiveProcessesError(e));
} }
} }
@ -54,10 +54,24 @@ export function *watchFetchProcesses() {
yield takeEvery(actions.FETCH_PROCESSES, fetchProcesses); yield takeEvery(actions.FETCH_PROCESSES, fetchProcesses);
} }
export function *fetchProcessLogs(action) {
try {
const logs = yield call(api.fetchProcessLogs, action.processName);
yield put(actions.receiveProcessLogs(action.processName, logs));
} catch (e) {
yield put(actions.receiveProcessLogsError(e));
}
}
export function *watchFetchProcessLogs() {
yield takeEvery(actions.FETCH_PROCESS_LOGS, fetchProcessLogs);
}
export default function *root() { export default function *root() {
yield all([ yield all([
fork(watchFetchAccounts), fork(watchFetchAccounts),
fork(watchFetchProcesses), fork(watchFetchProcesses),
fork(watchFetchProcessLogs),
fork(watchFetchBlocks), fork(watchFetchBlocks),
fork(watchFetchTransactions) fork(watchFetchTransactions)
]); ]);

View File

@ -21,6 +21,7 @@ class ProcessLauncher {
this.silent = options.silent; this.silent = options.silent;
this.exitCallback = options.exitCallback; this.exitCallback = options.exitCallback;
this.embark = options.embark; this.embark = options.embark;
this.logs = [];
this.subscriptions = {}; this.subscriptions = {};
this._subscribeToMessages(); this._subscribeToMessages();
@ -54,20 +55,29 @@ class ProcessLauncher {
_registerAsPlugin() { _registerAsPlugin() {
const self = this; const self = this;
const apiRoute = '/embark-api/process-logs/' + self.name;
self.embark.registerAPICall( self.embark.registerAPICall(
'ws', 'ws',
'/embark-api/process-logs/' + self.name, apiRoute,
(ws, _req) => { (ws, _req) => {
self.events.on('log-' + self.name, function(logLevel, msg) { self.events.on('process-log-' + self.name, function(logLevel, msg) {
ws.send(JSON.stringify({msg, msg_clear: msg.stripColors, logLevel}), () => {}); ws.send(JSON.stringify({msg, msg_clear: msg.stripColors, logLevel}), () => {});
}); });
} }
); );
self.embark.registerAPICall(
'get',
apiRoute,
(req, res) => {
res.send(JSON.stringify(self.logs));
}
);
} }
// Translates logs from the child process to the logger // Translates logs from the child process to the logger
_handleLog(msg) { _handleLog(msg) {
this.events.emit('log-' + this.name, msg.type, msg.message); this.events.emit('process-log-' + this.name, msg.type, msg.message);
this.logs.push({msg: msg.message, msg_clear: msg.message.stripColors, logLevel: msg.logLevel});
if (this.silent && msg.type !== 'error') { if (this.silent && msg.type !== 'error') {
return; return;
} }