mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
core: 速度优化:添加problem_list的projection支持
This commit is contained in:
1 parent
f78d19bebb
commit
0ed107bbba
8 files changed
+48
-19
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.13.25",
|
"version": "2.13.26",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class UserLoginHandler extends Handler {
|
|||||||
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
||||||
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
|
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
|
||||||
this.session.uid = udoc._id;
|
this.session.uid = udoc._id;
|
||||||
this.session.scope = PERM.PERM_ALL;
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
this.session.save = rememberme;
|
this.session.save = rememberme;
|
||||||
this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer;
|
this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ class UserLogoutHandler extends Handler {
|
|||||||
|
|
||||||
async post() {
|
async post() {
|
||||||
this.session.uid = 0;
|
this.session.uid = 0;
|
||||||
this.session.scope = PERM.PERM_ALL;
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ class OauthCallbackHandler extends Handler {
|
|||||||
const uid = await oauth.get(r._id);
|
const uid = await oauth.get(r._id);
|
||||||
if (uid) {
|
if (uid) {
|
||||||
this.session.uid = uid;
|
this.session.uid = uid;
|
||||||
this.session.scope = PERM.PERM_ALL;
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
} else {
|
} else {
|
||||||
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
||||||
let username = '';
|
let username = '';
|
||||||
@@ -262,7 +262,7 @@ class OauthCallbackHandler extends Handler {
|
|||||||
oauth.set(r.email, _id),
|
oauth.set(r.email, _id),
|
||||||
]);
|
]);
|
||||||
this.session.uid = _id;
|
this.session.uid = _id;
|
||||||
this.session.scope = PERM.PERM_ALL;
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc, ProblemStatusDoc,
|
Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc, ProblemStatusDoc,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import { NumberKeys, ArrayKeys } from '../typeutils';
|
import { buildProjection } from '../utils';
|
||||||
|
import { NumberKeys, ArrayKeys, Projection } from '../typeutils';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
import * as bus from '../service/bus';
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
@@ -82,8 +83,12 @@ export async function add(
|
|||||||
return docId || res.insertedId;
|
return docId || res.insertedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get<K extends keyof DocType>(domainId: string, docType: K, docId: DocType[K]['docId']) {
|
export async function get<K extends keyof DocType>(domainId: string, docType: K, docId: DocType[K]['docId'], projection?: Projection<DocType[K]>) {
|
||||||
return coll.findOne({ domainId, docType, docId });
|
let cursor = coll.find({ domainId, docType, docId }).limit(1);
|
||||||
|
if (projection) cursor = cursor.project(buildProjection(projection));
|
||||||
|
const result = await cursor.toArray();
|
||||||
|
if (result.length) return result[0];
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function set<K extends keyof DocType>(
|
export async function set<K extends keyof DocType>(
|
||||||
@@ -120,9 +125,11 @@ export function deleteMultiStatus<K extends keyof DocStatusType>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getMulti<K extends keyof DocType>(
|
export function getMulti<K extends keyof DocType>(
|
||||||
domainId: string, docType: K, query?: FilterQuery<DocType[K]>,
|
domainId: string, docType: K, query?: FilterQuery<DocType[K]>, projection?: Projection<DocType[K]>,
|
||||||
): Cursor<DocType[K]> {
|
): Cursor<DocType[K]> {
|
||||||
return coll.find({ ...query, docType, domainId });
|
let cursor = coll.find({ ...query, docType, domainId });
|
||||||
|
if (projection) cursor = cursor.project(buildProjection(projection));
|
||||||
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function inc<K extends keyof DocType>(
|
export async function inc<K extends keyof DocType>(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import * as domain from './domain';
|
|||||||
import {
|
import {
|
||||||
Pdoc, Pdict, ProblemDataSource, ProblemStatusDoc,
|
Pdoc, Pdict, ProblemDataSource, ProblemStatusDoc,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import { NumberKeys } from '../typeutils';
|
import { NumberKeys, Projection } from '../typeutils';
|
||||||
import { ProblemNotFoundError } from '../error';
|
import { ProblemNotFoundError } from '../error';
|
||||||
import * as testdataConfig from '../lib/testdataConfig';
|
import * as testdataConfig from '../lib/testdataConfig';
|
||||||
|
|
||||||
@@ -43,6 +43,17 @@ export const pdocHidden: Pdoc = {
|
|||||||
acMsg: '',
|
acMsg: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PROJECTION_LIST: Projection<Pdoc> = [
|
||||||
|
'_id', 'domainId', 'docType', 'docId', 'pid',
|
||||||
|
'owner', 'title', 'nSubmit', 'nAccept', 'difficulty',
|
||||||
|
'tag', 'category', 'hidden',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROJECTION_PUBLIC: Projection<Pdoc> = [
|
||||||
|
...PROJECTION_LIST,
|
||||||
|
'content', 'html', 'data', 'config', 'acMsg',
|
||||||
|
];
|
||||||
|
|
||||||
export async function add(
|
export async function add(
|
||||||
domainId: string, pid: string = null, title: string, content: string, owner: number,
|
domainId: string, pid: string = null, title: string, content: string, owner: number,
|
||||||
tag: string[] = [], category: string[] = [], data: ProblemDataSource = null, hidden = false,
|
tag: string[] = [], category: string[] = [], data: ProblemDataSource = null, hidden = false,
|
||||||
@@ -59,13 +70,13 @@ export async function add(
|
|||||||
|
|
||||||
export async function get(
|
export async function get(
|
||||||
domainId: string, pid: string | number,
|
domainId: string, pid: string | number,
|
||||||
uid: number = null,
|
uid: number = null, projection: Projection<Pdoc> = PROJECTION_PUBLIC,
|
||||||
): Promise<Pdoc> {
|
): Promise<Pdoc> {
|
||||||
if (typeof pid !== 'number') {
|
if (typeof pid !== 'number') {
|
||||||
if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10);
|
if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10);
|
||||||
}
|
}
|
||||||
const pdoc = typeof pid === 'number'
|
const pdoc = typeof pid === 'number'
|
||||||
? await document.get(domainId, document.TYPE_PROBLEM, pid)
|
? await document.get(domainId, document.TYPE_PROBLEM, pid, projection)
|
||||||
: (await document.getMulti(domainId, document.TYPE_PROBLEM, { pid }).toArray())[0];
|
: (await document.getMulti(domainId, document.TYPE_PROBLEM, { pid }).toArray())[0];
|
||||||
if (!pdoc) return null;
|
if (!pdoc) return null;
|
||||||
if (uid) {
|
if (uid) {
|
||||||
@@ -74,8 +85,8 @@ export async function get(
|
|||||||
return pdoc;
|
return pdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMulti(domainId: string, query: FilterQuery<Pdoc>) {
|
export function getMulti(domainId: string, query: FilterQuery<Pdoc>, projection = PROJECTION_LIST) {
|
||||||
return document.getMulti(domainId, document.TYPE_PROBLEM, query);
|
return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMultiStatus(domainId: string, query: FilterQuery<Pdoc>) {
|
export function getMultiStatus(domainId: string, query: FilterQuery<Pdoc>) {
|
||||||
@@ -162,6 +173,9 @@ export async function setTestdata(domainId: string, _id: number, filePath: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.model.problem = {
|
global.Hydro.model.problem = {
|
||||||
|
PROJECTION_LIST,
|
||||||
|
PROJECTION_PUBLIC,
|
||||||
|
|
||||||
SETTING_DIFFICULTY_ADMIN,
|
SETTING_DIFFICULTY_ADMIN,
|
||||||
SETTING_DIFFICULTY_ALGORITHM,
|
SETTING_DIFFICULTY_ALGORITHM,
|
||||||
SETTING_DIFFICULTY_AVERAGE,
|
SETTING_DIFFICULTY_AVERAGE,
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export class User implements _User {
|
|||||||
this.loginat = udoc.loginat;
|
this.loginat = udoc.loginat;
|
||||||
this.loginip = () => udoc.loginip;
|
this.loginip = () => udoc.loginip;
|
||||||
this.perm = () => dudoc.perm;
|
this.perm = () => dudoc.perm;
|
||||||
this.scope = () => scope;
|
this.scope = () => (typeof scope === 'string' ? BigInt(scope) : scope);
|
||||||
this.role = dudoc.role || 'default';
|
this.role = dudoc.role || 'default';
|
||||||
|
|
||||||
for (const key in setting.SETTINGS_BY_KEY) {
|
for (const key in setting.SETTINGS_BY_KEY) {
|
||||||
@@ -114,7 +114,7 @@ export class User implements _User {
|
|||||||
|
|
||||||
hasPerm(...perm: bigint[]) {
|
hasPerm(...perm: bigint[]) {
|
||||||
for (const i in perm) {
|
for (const i in perm) {
|
||||||
if ((this.perm() * this.scope() & perm[i]) === perm[i]) return true;
|
if ((this.perm() & this.scope() & perm[i]) === perm[i]) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,8 +483,8 @@ export class Handler {
|
|||||||
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
||||||
if (!this.user) {
|
if (!this.user) {
|
||||||
this.session.uid = 0;
|
this.session.uid = 0;
|
||||||
this.session.scope = PERM.PERM_ALL;
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
this.user = await user.getById(domainId, this.session.uid);
|
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
||||||
}
|
}
|
||||||
this.csrfToken = this.getCsrfToken(this.session._id || String.random(32));
|
this.csrfToken = this.getCsrfToken(this.session._id || String.random(32));
|
||||||
this.UIContext.csrfToken = this.csrfToken;
|
this.UIContext.csrfToken = this.csrfToken;
|
||||||
|
|||||||
@@ -9,3 +9,5 @@ export type ArrayKeys<O, P = any> = {
|
|||||||
export type Value<O, V = ''> = {
|
export type Value<O, V = ''> = {
|
||||||
[K in keyof O]: V
|
[K in keyof O]: V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Projection<O> = (string & keyof O)[]
|
||||||
@@ -179,3 +179,9 @@ export function streamToBuffer(stream): Promise<Buffer> {
|
|||||||
stream.on('end', () => resolve(Buffer.concat(buffers)));
|
stream.on('end', () => resolve(Buffer.concat(buffers)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildProjection(fields: string[]): Record<string, 1> {
|
||||||
|
const o = {};
|
||||||
|
for (const k of fields) o[k] = 1;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user