Commit 282422ec authored by Phil Hughes's avatar Phil Hughes

Merge branch '214685-exponentially-increase-page-size' into 'master'

Increase page size exponentially

See merge request gitlab-org/gitlab!65654
parents f4798c64 0175d9c7
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import filesQuery from 'shared_queries/repository/files.query.graphql'; import filesQuery from 'shared_queries/repository/files.query.graphql';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { __ } from '../../locale'; import { __ } from '../../locale';
import { TREE_PAGE_SIZE, TREE_INITIAL_FETCH_COUNT } from '../constants'; import { TREE_PAGE_SIZE, TREE_INITIAL_FETCH_COUNT, TREE_PAGE_LIMIT } from '../constants';
import getRefMixin from '../mixins/get_ref'; import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql'; import projectPathQuery from '../queries/project_path.query.graphql';
import { readmeFile } from '../utils/readme'; import { readmeFile } from '../utils/readme';
...@@ -36,6 +36,7 @@ export default { ...@@ -36,6 +36,7 @@ export default {
return { return {
projectPath: '', projectPath: '',
nextPageCursor: '', nextPageCursor: '',
pagesLoaded: 1,
entries: { entries: {
trees: [], trees: [],
submodules: [], submodules: [],
...@@ -44,16 +45,26 @@ export default { ...@@ -44,16 +45,26 @@ export default {
isLoadingFiles: false, isLoadingFiles: false,
isOverLimit: false, isOverLimit: false,
clickedShowMore: false, clickedShowMore: false,
pageSize: TREE_PAGE_SIZE,
fetchCounter: 0, fetchCounter: 0,
}; };
}, },
computed: { computed: {
pageSize() {
// we want to exponentially increase the page size to reduce the load on the frontend
const exponentialSize = (TREE_PAGE_SIZE / TREE_INITIAL_FETCH_COUNT) * (this.fetchCounter + 1);
return exponentialSize < TREE_PAGE_SIZE ? exponentialSize : TREE_PAGE_SIZE;
},
totalEntries() {
return Object.values(this.entries).flat().length;
},
readme() { readme() {
return readmeFile(this.entries.blobs); return readmeFile(this.entries.blobs);
}, },
pageLimitReached() {
return this.totalEntries / this.pagesLoaded >= TREE_PAGE_LIMIT;
},
hasShowMore() { hasShowMore() {
return !this.clickedShowMore && this.fetchCounter === TREE_INITIAL_FETCH_COUNT; return !this.clickedShowMore && this.pageLimitReached;
}, },
}, },
...@@ -104,7 +115,7 @@ export default { ...@@ -104,7 +115,7 @@ export default {
if (pageInfo?.hasNextPage) { if (pageInfo?.hasNextPage) {
this.nextPageCursor = pageInfo.endCursor; this.nextPageCursor = pageInfo.endCursor;
this.fetchCounter += 1; this.fetchCounter += 1;
if (this.fetchCounter < TREE_INITIAL_FETCH_COUNT || this.clickedShowMore) { if (!this.pageLimitReached || this.clickedShowMore) {
this.fetchFiles(); this.fetchFiles();
this.clickedShowMore = false; this.clickedShowMore = false;
} }
...@@ -127,6 +138,7 @@ export default { ...@@ -127,6 +138,7 @@ export default {
}, },
handleShowMore() { handleShowMore() {
this.clickedShowMore = true; this.clickedShowMore = true;
this.pagesLoaded += 1;
this.fetchFiles(); this.fetchFiles();
}, },
}, },
......
const TREE_PAGE_LIMIT = 1000; // the maximum amount of items per page export const TREE_PAGE_LIMIT = 1000; // the maximum amount of items per page
export const TREE_PAGE_SIZE = 100; // the amount of items to be fetched per (batch) request export const TREE_PAGE_SIZE = 100; // the amount of items to be fetched per (batch) request
export const TREE_INITIAL_FETCH_COUNT = TREE_PAGE_LIMIT / TREE_PAGE_SIZE; // the amount of (batch) requests to make export const TREE_INITIAL_FETCH_COUNT = TREE_PAGE_LIMIT / TREE_PAGE_SIZE; // the amount of (batch) requests to make
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import filesQuery from 'shared_queries/repository/files.query.graphql';
import FilePreview from '~/repository/components/preview/index.vue'; import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue'; import FileTable from '~/repository/components/table/index.vue';
import TreeContent from '~/repository/components/tree_content.vue'; import TreeContent from '~/repository/components/tree_content.vue';
import { TREE_INITIAL_FETCH_COUNT } from '~/repository/constants';
let vm; let vm;
let $apollo; let $apollo;
...@@ -23,6 +23,8 @@ function factory(path, data = () => ({})) { ...@@ -23,6 +23,8 @@ function factory(path, data = () => ({})) {
} }
describe('Repository table component', () => { describe('Repository table component', () => {
const findFileTable = () => vm.find(FileTable);
afterEach(() => { afterEach(() => {
vm.destroy(); vm.destroy();
}); });
...@@ -85,14 +87,12 @@ describe('Repository table component', () => { ...@@ -85,14 +87,12 @@ describe('Repository table component', () => {
describe('FileTable showMore', () => { describe('FileTable showMore', () => {
describe('when is present', () => { describe('when is present', () => {
const fileTable = () => vm.find(FileTable);
beforeEach(async () => { beforeEach(async () => {
factory('/'); factory('/');
}); });
it('is changes hasShowMore to false when "showMore" event is emitted', async () => { it('is changes hasShowMore to false when "showMore" event is emitted', async () => {
fileTable().vm.$emit('showMore'); findFileTable().vm.$emit('showMore');
await vm.vm.$nextTick(); await vm.vm.$nextTick();
...@@ -100,7 +100,7 @@ describe('Repository table component', () => { ...@@ -100,7 +100,7 @@ describe('Repository table component', () => {
}); });
it('changes clickedShowMore when "showMore" event is emitted', async () => { it('changes clickedShowMore when "showMore" event is emitted', async () => {
fileTable().vm.$emit('showMore'); findFileTable().vm.$emit('showMore');
await vm.vm.$nextTick(); await vm.vm.$nextTick();
...@@ -110,7 +110,7 @@ describe('Repository table component', () => { ...@@ -110,7 +110,7 @@ describe('Repository table component', () => {
it('triggers fetchFiles when "showMore" event is emitted', () => { it('triggers fetchFiles when "showMore" event is emitted', () => {
jest.spyOn(vm.vm, 'fetchFiles'); jest.spyOn(vm.vm, 'fetchFiles');
fileTable().vm.$emit('showMore'); findFileTable().vm.$emit('showMore');
expect(vm.vm.fetchFiles).toHaveBeenCalled(); expect(vm.vm.fetchFiles).toHaveBeenCalled();
}); });
...@@ -126,10 +126,52 @@ describe('Repository table component', () => { ...@@ -126,10 +126,52 @@ describe('Repository table component', () => {
expect(vm.vm.hasShowMore).toBe(false); expect(vm.vm.hasShowMore).toBe(false);
}); });
it('has limit of 1000 files on initial load', () => { it.each`
totalBlobs | pagesLoaded | limitReached
${900} | ${1} | ${false}
${1000} | ${1} | ${true}
${1002} | ${1} | ${true}
${1002} | ${2} | ${false}
${1900} | ${2} | ${false}
${2000} | ${2} | ${true}
`('has limit of 1000 entries per page', async ({ totalBlobs, pagesLoaded, limitReached }) => {
factory('/'); factory('/');
expect(TREE_INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000); const blobs = new Array(totalBlobs).fill('fakeBlob');
vm.setData({ entries: { blobs }, pagesLoaded });
await vm.vm.$nextTick();
expect(findFileTable().props('hasMore')).toBe(limitReached);
});
it.each`
fetchCounter | pageSize
${0} | ${10}
${2} | ${30}
${4} | ${50}
${6} | ${70}
${8} | ${90}
${10} | ${100}
${20} | ${100}
${100} | ${100}
${200} | ${100}
`('exponentially increases page size, to a maximum of 100', ({ fetchCounter, pageSize }) => {
factory('/');
vm.setData({ fetchCounter });
vm.vm.fetchFiles();
expect($apollo.query).toHaveBeenCalledWith({
query: filesQuery,
variables: {
pageSize,
nextPageCursor: '',
path: '/',
projectPath: '',
ref: '',
},
});
}); });
}); });
}); });
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