Commit bf3fcd03 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'polling-metrics-widget' into 'master'

Add polling to metrics widget

See merge request gitlab-org/gitlab!34314
parents fac0d3f9 cf583d92
import Visibility from 'visibilityjs';
import Poll from '~/lib/utils/poll';
import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
let eTagPoll;
export const clearEtagPoll = () => {
eTagPoll = null;
};
export const stopPolling = () => {
if (eTagPoll) eTagPoll.stop();
};
export const restartPolling = () => {
if (eTagPoll) eTagPoll.restart();
};
export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint); export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
export const requestMetrics = ({ commit }) => commit(types.REQUEST_METRICS); export const requestMetrics = ({ commit }) => commit(types.REQUEST_METRICS);
/**
* We need to poll the report endpoint while they are being parsed in the Backend.
* This can take up to one minute.
*
* Poll.js will handle etag response.
* While http status code is 204, it means it's parsing, and we'll keep polling
* When http status code is 200, it means parsing is done, we can show the results & stop polling
* When http status code is 500, it means parsing went wrong and we stop polling
*/
export const fetchMetrics = ({ state, dispatch }) => { export const fetchMetrics = ({ state, dispatch }) => {
dispatch('requestMetrics'); dispatch('requestMetrics');
return axios eTagPoll = new Poll({
.get(state.endpoint) resource: {
.then(response => dispatch('receiveMetricsSuccess', response.data)) getMetrics(endpoint) {
.catch(() => dispatch('receiveMetricsError')); return axios.get(endpoint);
},
},
data: state.endpoint,
method: 'getMetrics',
successCallback: ({ status, data }) => dispatch('receiveMetricsSuccess', { status, data }),
errorCallback: () => dispatch('receiveMetricsError'),
});
if (!Visibility.hidden()) {
eTagPoll.makeRequest();
} else {
axios
.get(state.endpoint)
.then(({ status, data }) => dispatch('receiveMetricsSuccess', { status, data }))
.catch(() => dispatch('receiveMetricsError'));
}
Visibility.change(() => {
if (!Visibility.hidden() && state.isLoading) {
dispatch('restartPolling');
} else {
dispatch('stopPolling');
}
});
}; };
export const receiveMetricsSuccess = ({ commit }, response) => { export const receiveMetricsSuccess = ({ commit, dispatch }, { status, data }) => {
commit(types.RECEIVE_METRICS_SUCCESS, response); if (status === httpStatusCodes.OK) {
commit(types.RECEIVE_METRICS_SUCCESS, data);
dispatch('stopPolling');
}
}; };
export const receiveMetricsError = ({ commit }) => commit(types.RECEIVE_METRICS_ERROR); export const receiveMetricsError = ({ commit, dispatch }) => {
commit(types.RECEIVE_METRICS_ERROR);
dispatch('stopPolling');
};
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
---
title: Add polling to metrics widget
merge_request: 34314
author:
type: changed
...@@ -5,6 +5,8 @@ import { ...@@ -5,6 +5,8 @@ import {
fetchMetrics, fetchMetrics,
receiveMetricsSuccess, receiveMetricsSuccess,
receiveMetricsError, receiveMetricsError,
stopPolling,
clearEtagPoll,
} from 'ee/vue_shared/metrics_reports/store/actions'; } from 'ee/vue_shared/metrics_reports/store/actions';
import * as types from 'ee/vue_shared/metrics_reports/store/mutation_types'; import * as types from 'ee/vue_shared/metrics_reports/store/mutation_types';
import state from 'ee/vue_shared/metrics_reports/store/state'; import state from 'ee/vue_shared/metrics_reports/store/state';
...@@ -58,17 +60,26 @@ describe('metrics reports actions', () => { ...@@ -58,17 +60,26 @@ describe('metrics reports actions', () => {
}); });
describe('fetchMetrics', () => { describe('fetchMetrics', () => {
it('should call metrics endpoint', () => { const data = {
const data = { metrics: [
metrics: [ {
{ name: 'name',
name: 'name', value: 'value',
value: 'value', },
}, ],
], };
}; const endpoint = '/mock-endpoint.json';
const endpoint = '/mock-endpoint.json';
beforeEach(() => {
mockedState.endpoint = endpoint; mockedState.endpoint = endpoint;
});
afterEach(() => {
stopPolling();
clearEtagPoll();
});
it('should call metrics endpoint', () => {
mock.onGet(endpoint).replyOnce(200, data); mock.onGet(endpoint).replyOnce(200, data);
return testAction( return testAction(
...@@ -81,7 +92,7 @@ describe('metrics reports actions', () => { ...@@ -81,7 +92,7 @@ describe('metrics reports actions', () => {
type: 'requestMetrics', type: 'requestMetrics',
}, },
{ {
payload: data, payload: { status: 200, data },
type: 'receiveMetricsSuccess', type: 'receiveMetricsSuccess',
}, },
], ],
...@@ -89,8 +100,6 @@ describe('metrics reports actions', () => { ...@@ -89,8 +100,6 @@ describe('metrics reports actions', () => {
}); });
it('handles errors', () => { it('handles errors', () => {
const endpoint = '/mock-endpoint.json';
mockedState.endpoint = endpoint;
mock.onGet(endpoint).replyOnce(500); mock.onGet(endpoint).replyOnce(500);
return testAction( return testAction(
...@@ -111,11 +120,11 @@ describe('metrics reports actions', () => { ...@@ -111,11 +120,11 @@ describe('metrics reports actions', () => {
}); });
describe('receiveMetricsSuccess', () => { describe('receiveMetricsSuccess', () => {
it('should commit request mutation', () => { it('should commit request mutation with 200', () => {
const response = { metrics: [] }; const response = { metrics: [] };
return testAction( return testAction(
receiveMetricsSuccess, receiveMetricsSuccess,
response, { status: 200, data: response },
mockedState, mockedState,
[ [
{ {
...@@ -123,6 +132,17 @@ describe('metrics reports actions', () => { ...@@ -123,6 +132,17 @@ describe('metrics reports actions', () => {
payload: response, payload: response,
}, },
], ],
[{ type: 'stopPolling' }],
);
});
it('should not commit request mutation with 204', () => {
const response = { metrics: [] };
return testAction(
receiveMetricsSuccess,
{ status: 204, data: response },
mockedState,
[],
[], [],
); );
}); });
...@@ -139,7 +159,7 @@ describe('metrics reports actions', () => { ...@@ -139,7 +159,7 @@ describe('metrics reports actions', () => {
type: types.RECEIVE_METRICS_ERROR, type: types.RECEIVE_METRICS_ERROR,
}, },
], ],
[], [{ type: 'stopPolling' }],
); );
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment