core&ui: performance optimization

This commit is contained in:
undefined committed 2022-11-27 16:16:21 +08:00
1 parent b1e5c77a56
commit 73aa641258
7 files changed
+31 -22

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "4.4.0", "version": "4.4.1",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "src/plugin-api", "main": "src/plugin-api",
"module": "src/plugin-api", "module": "src/plugin-api",
+1 -1
View File
@@ -171,7 +171,7 @@ class RecordDetailHandler extends ContestDetailBaseHandler {
canViewCode ||= tsdoc?.attend; canViewCode ||= tsdoc?.attend;
} }
if (!tsdoc?.attend && !problem.canViewBy(pdoc, this.user)) throw new PermissionError(PERM.PERM_VIEW_PROBLEM_HIDDEN); if (!tsdoc?.attend && !problem.canViewBy(pdoc, this.user)) throw new PermissionError(PERM.PERM_VIEW_PROBLEM_HIDDEN);
} else if (!problem.canViewBy(pdoc, this.user)) throw new PermissionError(PERM.PERM_VIEW_PROBLEM_HIDDEN); } else if (pdoc && !problem.canViewBy(pdoc, this.user)) throw new PermissionError(PERM.PERM_VIEW_PROBLEM_HIDDEN);
if (!canViewCode) { if (!canViewCode) {
rdoc.code = ''; rdoc.code = '';
rdoc.files = {}; rdoc.files = {};
+13 -9
View File
@@ -9,6 +9,7 @@ import problem from '../model/problem';
import * as system from '../model/system'; import * as system from '../model/system';
import * as training from '../model/training'; import * as training from '../model/training';
import user from '../model/user'; import user from '../model/user';
import { DomainModel } from '../plugin-api';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
import { Handler, param, Types } from '../service/server'; import { Handler, param, Types } from '../service/server';
@@ -97,7 +98,7 @@ class TrainingDetailHandler extends Handler {
const tdoc = await training.get(domainId, tid); const tdoc = await training.get(domainId, tid);
await bus.parallel('training/get', tdoc, this); await bus.parallel('training/get', tdoc, this);
let targetUser = this.user._id; let targetUser = this.user._id;
let enrollUsers = []; let enrollUsers: number[] = [];
let shouldCompare = false; let shouldCompare = false;
const pids = training.getPids(tdoc.dag); const pids = training.getPids(tdoc.dag);
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) { if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
@@ -109,21 +110,24 @@ class TrainingDetailHandler extends Handler {
} }
} }
const canViewHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id; const canViewHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id;
const [udict, pdict] = await Promise.all([ const [udoc, udocs, dudocs, pdict, psdict, selfPsdict] = await Promise.all([
user.getList(domainId, [tdoc.owner, ...enrollUsers]), user.getById(domainId, tdoc.owner),
user.getMulti({ _id: { $in: enrollUsers } }).project({ _id: 1, uname: 1, avatar: 1 }).toArray(),
DomainModel.getDomainUserMulti(domainId, enrollUsers).project({ uid: 1, displayName: 1 }).toArray(),
problem.getList(domainId, pids, canViewHidden, true), problem.getList(domainId, pids, canViewHidden, true),
problem.getListStatus(domainId, targetUser, pids),
shouldCompare ? problem.getListStatus(domainId, this.user._id, pids) : {},
]); ]);
const psdict = await problem.getListStatus(domainId, targetUser, pids); const dudict = {};
const selfPsdict = shouldCompare ? await problem.getListStatus(domainId, this.user._id, pids) : {}; for (const dudoc of dudocs) dudict[dudoc.uid] = dudoc.displayName;
const donePids = new Set<number>(); const donePids = new Set<number>();
const progPids = new Set<number>(); const progPids = new Set<number>();
for (const pid in psdict) { for (const pid in psdict) {
if (!+pid) continue; if (!+pid) continue;
const psdoc = psdict[pid]; const psdoc = psdict[pid];
if (psdoc.status) { if (psdoc.status) {
if (psdoc.status === builtin.STATUS.STATUS_ACCEPTED) { if (psdoc.status === builtin.STATUS.STATUS_ACCEPTED) donePids.add(+pid);
donePids.add(parseInt(pid, 10)); else progPids.add(+pid);
} else progPids.add(parseInt(pid, 10));
} }
} }
const nsdict = {}; const nsdict = {};
@@ -149,7 +153,7 @@ class TrainingDetailHandler extends Handler {
done: doneNids.size === tdoc.dag.length, done: doneNids.size === tdoc.dag.length,
}); });
this.response.body = { this.response.body = {
tdoc, tsdoc, pids, pdict, psdict, ndict, nsdict, udict, enrollUsers, selfPsdict, tdoc, tsdoc, pids, pdict, psdict, ndict, nsdict, udoc, udocs, dudict, selfPsdict,
}; };
if (pjax) { if (pjax) {
const html = await this.renderHTML('partials/training_detail.html', this.response.body); const html = await this.renderHTML('partials/training_detail.html', this.response.body);
+4
View File
@@ -189,6 +189,10 @@ class DomainModel {
return dudoc; return dudoc;
} }
static getDomainUserMulti(domainId: string, uids: number[]) {
return collUser.find({ domainId, uid: { $in: uids } });
}
static setMultiUserInDomain(domainId: string, query: any, params: any) { static setMultiUserInDomain(domainId: string, query: any, params: any) {
deleteUserCache(domainId); deleteUserCache(domainId);
return collUser.updateMany({ domainId, ...query }, { $set: params }, { upsert: true }); return collUser.updateMany({ domainId, ...query }, { $set: params }, { upsert: true });
+2 -1
View File
@@ -10,7 +10,7 @@ import { createPresignedPost } from '@aws-sdk/s3-presigned-post';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { import {
copyFile, createReadStream, createWriteStream, ensureDir, copyFile, createReadStream, createWriteStream, ensureDir,
remove, stat, writeFile, existsSync, remove, stat, writeFile,
} from 'fs-extra'; } from 'fs-extra';
import { lookup } from 'mime-types'; import { lookup } from 'mime-types';
import { Logger } from '../logger'; import { Logger } from '../logger';
@@ -273,6 +273,7 @@ class LocalStorageService {
async get(target: string, path?: string) { async get(target: string, path?: string) {
if (target.includes('..') || target.includes('//')) throw new Error('Invalid path'); if (target.includes('..') || target.includes('//')) throw new Error('Invalid path');
target = resolve(this.dir, target); target = resolve(this.dir, target);
if (!existsSync(target)) throw new Error('File not found');
if (path) await copyFile(target, path); if (path) await copyFile(target, path);
return createReadStream(target); return createReadStream(target);
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/ui-default", "name": "@hydrooj/ui-default",
"version": "4.42.19", "version": "4.42.20",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "index.ts", "main": "index.ts",
@@ -1,7 +1,7 @@
{% extends "layout/basic.html" %} {% extends "layout/basic.html" %}
{% block content %} {% block content %}
<div class="row" data-sticky-parent> <div class="row" data-sticky-parent>
{%- if enrollUsers.length -%} {%- if udocs.length -%}
<div class="medium-2 columns mobile--hide"> <div class="medium-2 columns mobile--hide">
<div data-sticky="large"><div class="section side"> <div data-sticky="large"><div class="section side">
<ol class="menu"> <ol class="menu">
@@ -11,16 +11,16 @@
</form> </form>
</li> </li>
<ul class="enroll_user_menu"> <ul class="enroll_user_menu">
{%- for uid in enrollUsers -%} {%- for udoc in udocs -%}
<li class="menu__item enroll_user_menu_item" data-uid="{{ uid }}" data-uname="{{ udict[uid].uname }}"> <li class="menu__item enroll_user_menu_item" data-uid="{{ udoc._id }}" data-uname="{{ udoc.uname }}">
<a href="./{{ tdoc._id }}?uid={{ uid }}" class="menu__link{% if (handler.request.query.uid or handler.user._id) == uid %} active{% endif %}"> <a href="./{{ tdoc._id }}?uid={{ udoc._id }}" class="menu__link{% if (handler.request.query.uid or handler.user._id) == uid %} active{% endif %}">
<span class="user-profile-link"> <span class="user-profile-link">
<img class="small user-profile-avatar v-center" loading="lazy" src="{{ avatarUrl(udict[uid].avatar|default('')) }}" width="20" height="20"> <img class="small user-profile-avatar v-center" loading="lazy" src="{{ avatarUrl(udoc.avatar|default('')) }}" width="20" height="20">
<span class="user-profile-name"> <span class="user-profile-name">
{% if handler.user.hasPerm(perm.PREM_VIEW_DISPLAYNAME) and udict[uid].displayName and udict[uid].displayName != udict[uid].uname %} {% if handler.user.hasPerm(perm.PREM_VIEW_DISPLAYNAME) and dudict[udoc._id] and dudict[udoc._id] != udoc.uname %}
{{ udict[uid].displayName }} ({{ udict[uid].uname }}) {{ dudict[udoc._id] }} ({{ udoc.uname }})
{% else %} {% else %}
{{ udict[uid].uname }} {{ udoc.uname }}
{% endif %} {% endif %}
</span> </span>
</span> </span>
@@ -92,7 +92,7 @@
{% endif %} {% endif %}
<dt>{{ _('Enrollees') }}</dt><dd>{{ tdoc.attend|default(0) }}</dd> <dt>{{ _('Enrollees') }}</dt><dd>{{ tdoc.attend|default(0) }}</dd>
<dt>{{ _('Created By') }}</dt> <dt>{{ _('Created By') }}</dt>
<dd>{{ user.render_inline(udict[tdoc.owner], badge=false) }}</dd> <dd>{{ user.render_inline(udoc, badge=false) }}</dd>
</dl> </dl>
</div> </div>
</div> </div>