Skip to content
Snippets Groups Projects
Commit ecbf7ecd authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms Committed by Jan-Hendrik Willms
Browse files

limit number of parallel requests and cache gained info, fixes #4358

Closes #4358

Merge request studip/studip!3161
parent 7a332f87
No related branches found
No related tags found
No related merge requests found
import axios from "axios";
interface ChunkedRequest {
url: string,
parameters: object,
resolve(value: any): any,
reject(): any,
}
export default class ChunkedRequester
{
#requests: ChunkedRequest[] = [];
readonly #delay: number;
readonly #limit: number;
#timeout: any = null;
constructor(limit: number = 16, delay: number = 500) {
if (limit < 1) {
throw new Error('Limit must be positive');
}
this.#limit = limit;
this.#delay = delay;
}
addRequest(url: string, parameters: object = {}): Promise<any>
{
return new Promise((resolve, reject) => {
this.#requests.push({
url,
parameters,
resolve,
reject
});
this.#startRequests();
});
}
#startRequests(): void
{
if (this.#requests.length === 0) {
return;
}
if (this.#requests.length < this.#limit) {
this.clearTimeout();
}
if (this.#timeout !== null) {
return;
}
this.#timeout = setTimeout(
() => {
Promise.all(
this.#requests
.splice(0, this.#limit)
.map(({url, parameters, resolve, reject}) => {
return axios.get(url, {params: parameters}).then(resolve, reject);
})
).then(() => {
this.clearTimeout();
this.#startRequests();
});
}
, this.#delay
);
}
clearTimeout(): void
{
clearTimeout(this.#timeout);
this.#timeout = null;
}
}
...@@ -222,7 +222,7 @@ export default { ...@@ -222,7 +222,7 @@ export default {
courses: [], courses: [],
assistiveLive: '', assistiveLive: '',
subLevelsCourses: 0, subLevelsCourses: 0,
thisLevelCourses: 0, thisLevelCourses: this.getCachedNodeCourseInfo(this.node.id, this.semester, this.semClass),
showingAllCourses: false showingAllCourses: false
} }
}, },
......
...@@ -245,7 +245,7 @@ export default { ...@@ -245,7 +245,7 @@ export default {
courses: [], courses: [],
assistiveLive: '', assistiveLive: '',
subLevelsCourses: 0, subLevelsCourses: 0,
thisLevelCourses: 0, thisLevelCourses: this.getCachedNodeCourseInfo(this.node.id, this.semester, this.semClass),
showingAllCourses: false showingAllCourses: false
} }
}, },
......
...@@ -32,22 +32,24 @@ export default { ...@@ -32,22 +32,24 @@ export default {
}, },
data() { data() {
return { return {
isLoading: false, courseCount: this.getCachedNodeCourseInfo(this.node, this.semester, this.semClass),
courseCount: 0,
showingAllCourses: false showingAllCourses: false
} }
}, },
computed: {
isLoading() {
return this.courseCount === null;
}
},
methods: { methods: {
showAllCourses(state) { showAllCourses(state) {
this.showingAllCourses = state; this.showingAllCourses = state;
this.$emit('showAllCourses', state); this.$emit('showAllCourses', state);
}, },
loadNodeInfo(node) { loadNodeInfo(node) {
this.isLoading = true;
this.getNodeCourseInfo(node, this.semester, this.semClass) this.getNodeCourseInfo(node, this.semester, this.semClass)
.then(info => { .then(info => {
this.courseCount = info?.data.courses; this.courseCount = info?.data.courses ?? 0;
this.isLoading = false;
}); });
} }
}, },
......
import axios from 'axios'; import axios from 'axios';
import ChunkedRequester from '@/assets/javascripts/lib/chunked-requester';
import Cache from '@/assets/javascripts/lib/cache';
const requester = new ChunkedRequester();
const cache = Cache.getInstance('tree-info/');
export const TreeMixin = { export const TreeMixin = {
data() { data() {
...@@ -56,7 +61,10 @@ export const TreeMixin = { ...@@ -56,7 +61,10 @@ export const TreeMixin = {
{params: parameters} {params: parameters}
); );
}, },
async getNodeCourseInfo(node, semesterId, semClass = 0) { getCachedNodeCourseInfo(node, semesterId, semClass) {
return cache.get(['course-info', node.id, semesterId, semClass].join('/')) ?? null;
},
getNodeCourseInfo(node, semesterId, semClass = 0) {
let parameters = {}; let parameters = {};
if (semesterId !== 'all' && semesterId !== '0') { if (semesterId !== 'all' && semesterId !== '0') {
...@@ -67,10 +75,17 @@ export const TreeMixin = { ...@@ -67,10 +75,17 @@ export const TreeMixin = {
parameters['filter[semclass]'] = semClass; parameters['filter[semclass]'] = semClass;
} }
return axios.get( return requester.addRequest(
STUDIP.URLHelper.getURL('jsonapi.php/v1/tree-node/' + node.id + '/courseinfo'), STUDIP.URLHelper.getURL('jsonapi.php/v1/tree-node/' + node.id + '/courseinfo'),
{ params: parameters } parameters
); ).then(courseinfo => {
cache.set(
['course-info', node.id, semesterId, semClass].join('/'),
courseinfo.data.courses ?? 0,
3 * 60 * 60
);
return courseinfo;
});
}, },
nodeUrl(node_id, semester = null ) { nodeUrl(node_id, semester = null ) {
return STUDIP.URLHelper.getURL('', { node_id, semester }) return STUDIP.URLHelper.getURL('', { node_id, semester })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment