1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-11 00:08:30 +01:00

Move metrics poller to seperate class

This commit is contained in:
Ivar Conradi Østhus 2018-01-29 09:07:10 +01:00
parent 03ff3b8a74
commit f540389189
10 changed files with 131 additions and 21 deletions

View File

@ -72,12 +72,14 @@
"eslint-config-finn-react": "^2.0.0",
"eslint-plugin-react": "^7.3.0",
"extract-text-webpack-plugin": "^3.0.0",
"fetch-mock": "^6.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^22.1.2",
"node-sass": "^4.5.3",
"prettier": "^1.8.2",
"react-test-renderer": "^15.6.1",
"redux-devtools": "^3.3.1",
"redux-mock-store": "^1.5.1",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"toolbox-loader": "0.0.3",

View File

@ -0,0 +1,5 @@
{
"env": {
"jest": true
}
}

View File

@ -0,0 +1,63 @@
import configureStore from 'redux-mock-store';
import thunkMiddleware from 'redux-thunk';
import fetchMock from 'fetch-mock';
import MetricsPoller from '../metrics-poller';
const mockStore = configureStore([thunkMiddleware]);
describe('metrics-poller.js', () => {
afterEach(() => {
fetchMock.reset();
fetchMock.restore();
});
test('Should not start poller before toggles are recieved', () => {
const initialState = { features: [{ name: 'test1' }] };
const store = mockStore(initialState);
fetchMock.getOnce('api/admin/metrics/feature-toggles', {
body: { lastHour: {}, lastMinute: {} },
headers: { 'content-type': 'application/json' },
});
const metricsPoller = new MetricsPoller(store);
metricsPoller.start();
expect(metricsPoller.timer).toBeUndefined();
});
test('Should not start poller when state does not contain toggles', () => {
const initialState = { features: [] };
const store = mockStore(initialState);
const metricsPoller = new MetricsPoller(store);
metricsPoller.start();
store.dispatch({
type: 'some',
receivedAt: Date.now(),
});
expect(metricsPoller.timer).toBeUndefined();
});
test('Should start poller when state gets toggles', () => {
fetchMock.getOnce('api/admin/metrics/feature-toggles', {
body: { lastHour: {}, lastMinute: {} },
headers: { 'content-type': 'application/json' },
});
const initialState = { features: [{ name: 'test1' }] };
const store = mockStore(initialState);
const metricsPoller = new MetricsPoller(store);
metricsPoller.start();
store.dispatch({
type: 'RECEIVE_FEATURE_TOGGLES',
featureToggles: [{ name: 'test' }],
receivedAt: Date.now(),
});
expect(metricsPoller.timer).toBeDefined();
});
});

View File

@ -12,7 +12,6 @@ export default class FeatureListComponent extends React.PureComponent {
features: PropTypes.array.isRequired,
featureMetrics: PropTypes.object.isRequired,
fetchFeatureToggles: PropTypes.func.isRequired,
fetchFeatureMetrics: PropTypes.func.isRequired,
updateSetting: PropTypes.func.isRequired,
settings: PropTypes.object,
};
@ -23,15 +22,6 @@ export default class FeatureListComponent extends React.PureComponent {
componentDidMount() {
this.props.fetchFeatureToggles();
this.props.fetchFeatureMetrics();
this.timer = setInterval(() => {
// this.props.fetchFeatureToggles();
this.props.fetchFeatureMetrics();
}, 5000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
toggleMetrics() {

View File

@ -1,6 +1,5 @@
import { connect } from 'react-redux';
import { toggleFeature, fetchFeatureToggles } from '../../store/feature-actions';
import { fetchFeatureMetrics } from '../../store/feature-metrics-actions';
import { updateSettingForGroup } from '../../store/settings/actions';
import FeatureListComponent from './list-component';
@ -74,7 +73,6 @@ const mapStateToProps = state => {
const mapDispatchToProps = {
toggleFeature,
fetchFeatureToggles,
fetchFeatureMetrics,
updateSetting: updateSettingForGroup('feature'),
};

View File

@ -37,13 +37,6 @@ export default class MetricComponent extends React.Component {
componentWillMount() {
this.props.fetchSeenApps();
this.props.fetchFeatureMetrics();
this.timer = setInterval(() => {
this.props.fetchFeatureMetrics();
}, 5000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {

View File

@ -25,8 +25,8 @@ export default class ViewFeatureToggleComponent extends React.Component {
features: PropTypes.array.isRequired,
toggleFeature: PropTypes.func.isRequired,
removeFeatureToggle: PropTypes.func.isRequired,
fetchFeatureToggles: PropTypes.array.isRequired,
featureToggle: PropTypes.object.isRequired,
fetchFeatureToggles: PropTypes.func.isRequired,
featureToggle: PropTypes.object,
};
componentWillMount() {

View File

@ -11,6 +11,7 @@ import thunkMiddleware from 'redux-thunk';
import { createStore, applyMiddleware, compose } from 'redux';
import store from './store';
import MetricsPoller from './metrics-poller';
import App from './component/app';
import Features from './page/features';
@ -34,6 +35,8 @@ if (process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_C
}
const unleashStore = createStore(store, composeEnhancers(applyMiddleware(thunkMiddleware)));
const metricsPoller = new MetricsPoller(unleashStore);
metricsPoller.start();
// "pageTitle" and "link" attributes are for internal usage only

View File

@ -0,0 +1,31 @@
import { fetchFeatureMetrics } from './store/feature-metrics-actions';
class MetricsPoller {
constructor(store) {
this.store = store;
this.timer = undefined;
}
start() {
this.store.subscribe(() => {
const features = this.store.getState().features;
if (!this.timer && features.length > 0) {
this.timer = setInterval(this.fetchMetrics.bind(this), 5000);
this.fetchMetrics();
}
});
}
fetchMetrics() {
this.store.dispatch(fetchFeatureMetrics());
}
destroy() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = undefined;
}
}
}
export default MetricsPoller;

View File

@ -2462,6 +2462,13 @@ fbjs@^0.8.16, fbjs@^0.8.9:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fetch-mock@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-6.0.0.tgz#4edb5acefa8ea90d7eb4213130ab73137fac9df1"
dependencies:
glob-to-regexp "^0.3.0"
path-to-regexp "^2.1.0"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
@ -2684,6 +2691,10 @@ glob-parent@^2.0.0:
dependencies:
is-glob "^2.0.0"
glob-to-regexp@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
@ -3858,6 +3869,10 @@ lodash.isequal@^4.4.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@ -4493,6 +4508,10 @@ path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
path-to-regexp@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.1.0.tgz#7e30f9f5b134bd6a28ffc2e3ef1e47075ac5259b"
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@ -5204,6 +5223,12 @@ redux-devtools@^3.3.1:
prop-types "^15.5.7"
redux-devtools-instrument "^1.0.1"
redux-mock-store@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.1.tgz#fca4335392e66605420b5559fe02fc5b8bb6d63c"
dependencies:
lodash.isplainobject "^4.0.6"
redux-thunk@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"