Skip to content
代码片段 群组 项目
未验证 提交 e58459b9 编辑于 作者: Artur Fedorov's avatar Artur Fedorov 提交者: GitLab
浏览文件

Merge branch 'drosse/cancel-metrics-query' into 'master'

Add support for cancelling metrics search query

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144660



Merged-by: default avatarArtur Fedorov <afedorov@gitlab.com>
Approved-by: default avatarJay Montal <jmontal@gitlab.com>
Approved-by: default avatarArtur Fedorov <afedorov@gitlab.com>
Co-authored-by: default avatarDaniele Rossetti <drossetti@gitlab.com>
No related branches found
No related tags found
无相关合并请求
......@@ -410,6 +410,7 @@ async function fetchMetric(searchUrl, name, type, options = {}) {
const { data } = await axios.get(searchUrl, {
params,
signal: options.abortController?.signal,
withCredentials: true,
});
......
......@@ -9,6 +9,7 @@ import {
processFilters as processFilteredSearchFilters,
} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import { periodToDate } from '~/observability/utils';
import axios from '~/lib/utils/axios_utils';
import { ingestedAtTimeAgo } from '../utils';
import MetricsChart from './metrics_chart.vue';
import FilteredSearch from './filter_bar/metrics_filtered_search.vue';
......@@ -63,6 +64,7 @@ export default {
endDate: defaultRange.max,
},
},
apiAbortController: null,
loading: false,
};
},
......@@ -122,16 +124,20 @@ export default {
async fetchMetricData() {
this.loading = true;
try {
this.apiAbortController = new AbortController();
this.metricData = await this.observabilityClient.fetchMetric(
this.metricId,
this.metricType,
{ filters: this.filters },
{ filters: this.filters, abortController: this.apiAbortController },
);
} catch (e) {
createAlert({
message: this.$options.i18n.error,
});
if (!axios.isCancel(e)) {
createAlert({
message: this.$options.i18n.error,
});
}
} finally {
this.apiAbortController = null;
this.loading = false;
}
},
......
......@@ -9,9 +9,11 @@ import MetricsChart from 'ee/metrics/details/metrics_chart.vue';
import FilteredSearch from 'ee/metrics/details/filter_bar/metrics_filtered_search.vue';
import { ingestedAtTimeAgo } from 'ee/metrics/utils';
import { prepareTokens } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/alert');
jest.mock('~/lib/utils/url_utility');
jest.mock('~/lib/utils/axios_utils');
jest.mock('ee/metrics/utils');
describe('MetricsDetails', () => {
......@@ -121,11 +123,10 @@ describe('MetricsDetails', () => {
});
it('renders the metrics details', () => {
expect(observabilityClientMock.fetchMetric).toHaveBeenCalledWith(
METRIC_ID,
METRIC_TYPE,
expect.any(Object),
);
expect(observabilityClientMock.fetchMetric).toHaveBeenCalledWith(METRIC_ID, METRIC_TYPE, {
abortController: expect.any(AbortController),
filters: expect.any(Object),
});
expect(findLoadingIcon().exists()).toBe(false);
expect(findMetricDetails().exists()).toBe(true);
});
......@@ -154,6 +155,7 @@ describe('MetricsDetails', () => {
it('fetches metrics with filters', () => {
expect(observabilityClientMock.fetchMetric).toHaveBeenCalledWith(METRIC_ID, METRIC_TYPE, {
abortController: expect.any(AbortController),
filters: {
attributes: [],
dateRange: {
......@@ -197,6 +199,7 @@ describe('MetricsDetails', () => {
METRIC_ID,
METRIC_TYPE,
{
abortController: expect.any(AbortController),
filters: {
attributes: {
'key.one': [{ operator: '=', value: '12h' }],
......@@ -287,10 +290,10 @@ describe('MetricsDetails', () => {
});
describe('error handling', () => {
beforeEach(async () => {
observabilityClientMock.isObservabilityEnabled.mockRejectedValueOnce('error');
await mountComponent();
beforeEach(() => {
observabilityClientMock.isObservabilityEnabled.mockResolvedValue(true);
observabilityClientMock.fetchMetric.mockResolvedValue([]);
observabilityClientMock.fetchMetricSearchMetadata.mockResolvedValue([]);
});
describe.each([
......@@ -299,7 +302,7 @@ describe('MetricsDetails', () => {
['fetchMetric', () => observabilityClientMock.fetchMetric],
])('when %s fails', (_, mockFn) => {
beforeEach(async () => {
mockFn().mockRejectedValueOnce('error');
mockFn().mockRejectedValue('error');
await mountComponent();
});
it('renders an alert', () => {
......@@ -332,5 +335,14 @@ describe('MetricsDetails', () => {
message: 'Error: Failed to load metrics details. Try reloading the page.',
});
});
it('does not render an alert if the api call fails because cancelled', async () => {
observabilityClientMock.fetchMetric.mockRejectedValueOnce('cancelled');
axios.isCancel = jest.fn().mockReturnValue(true);
await mountComponent();
expect(createAlert).not.toHaveBeenCalled();
});
});
});
......@@ -782,6 +782,19 @@ describe('buildClient', () => {
expect(result).toEqual(data.results);
});
it('passes the abort controller to axios', async () => {
axiosMock.onGet(metricsSearchUrl).reply(200, { results: [] });
const abortController = new AbortController();
await client.fetchMetric('name', 'type', { abortController });
expect(axios.get).toHaveBeenCalledWith(metricsSearchUrl, {
withCredentials: true,
params: new URLSearchParams({ mname: 'name', mtype: 'type' }),
signal: abortController.signal,
});
});
describe('query filter params', () => {
beforeEach(() => {
axiosMock.onGet(metricsSearchUrl).reply(200, { results: [] });
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册