Commit cf583d92 authored by Frederic Caplette's avatar Frederic Caplette

Add polling to metrics widget

Add polling to metrics widget
to have up to date status in MR.
parent 99071b7b
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({
resource: {
getMetrics(endpoint) {
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) .get(state.endpoint)
.then(response => dispatch('receiveMetricsSuccess', response.data)) .then(({ status, data }) => dispatch('receiveMetricsSuccess', { status, data }))
.catch(() => dispatch('receiveMetricsError')); .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,7 +60,6 @@ describe('metrics reports actions', () => { ...@@ -58,7 +60,6 @@ describe('metrics reports actions', () => {
}); });
describe('fetchMetrics', () => { describe('fetchMetrics', () => {
it('should call metrics endpoint', () => {
const data = { const data = {
metrics: [ metrics: [
{ {
...@@ -68,7 +69,17 @@ describe('metrics reports actions', () => { ...@@ -68,7 +69,17 @@ describe('metrics reports actions', () => {
], ],
}; };
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