mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 09:38:19 +08:00
添加cache-loader,debug模式下不再使用template缓存,修复一些 bug
This commit is contained in:
1 parent
dd7914e1fb
commit
11368bc831
21 files changed
+248
-266
No files matched your search
@@ -375,6 +375,7 @@ class ContestCreateHandler extends ContestHandler {
|
||||
}
|
||||
|
||||
export async function apply() {
|
||||
Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST);
|
||||
Route('contest_main', '/contest', ContestListHandler, PERM.PERM_VIEW_CONTEST);
|
||||
Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST);
|
||||
Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST);
|
||||
@@ -383,7 +384,6 @@ export async function apply() {
|
||||
Route('contest_detail_problem', '/contest/:tid/p/:pid', ContestProblemHandler, PERM.PERM_VIEW_CONTEST);
|
||||
Route('contest_detail_problem_submit', '/contest/:tid/p/:pid/submit', ContestProblemSubmitHandler, PERM.PERM_VIEW_CONTEST);
|
||||
Route('contest_code', '/contest/:tid/code', ContestCodeHandler, PERM.PERM_VIEW_CONTEST);
|
||||
Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST);
|
||||
}
|
||||
|
||||
global.Hydro.handler.contest = apply;
|
||||
+26
-10
@@ -1,4 +1,5 @@
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { isSafeInteger } from 'lodash';
|
||||
import { DiscussionNotFoundError, DocumentNotFoundError } from '../error';
|
||||
import paginate from '../lib/paginate';
|
||||
import * as system from '../model/system';
|
||||
@@ -87,17 +88,23 @@ class DiscussionMainHandler extends Handler {
|
||||
}
|
||||
|
||||
class DiscussionNodeHandler extends DiscussionHandler {
|
||||
async get({
|
||||
domainId, type, name, page = 1,
|
||||
}) {
|
||||
if (ObjectID.isValid(name)) name = new ObjectID(name);
|
||||
@param('type', Types.String)
|
||||
@param('name', Types.String)
|
||||
@param('page', Types.UnsignedInt, true)
|
||||
async get(domainId: string, type: string, _name: string, page = 1) {
|
||||
let name: ObjectID | string | number;
|
||||
if (ObjectID.isValid(_name)) name = new ObjectID(_name);
|
||||
else if (isSafeInteger(parseInt(_name, 10))) name = parseInt(_name, 10);
|
||||
else name = _name;
|
||||
const [ddocs, dpcount] = await paginate(
|
||||
discussion.getMulti(domainId, { parentType: typeMapper[type], parentId: name }),
|
||||
page,
|
||||
await system.get('DISCUSSION_PER_PAGE'),
|
||||
);
|
||||
const uids = ddocs.map((ddoc) => ddoc.owner);
|
||||
uids.push(this.vnode.owner);
|
||||
const [udict, vnodes] = await Promise.all([
|
||||
user.getList(domainId, ddocs.map((ddoc) => ddoc.owner)),
|
||||
user.getList(domainId, uids),
|
||||
discussion.getNodes(domainId),
|
||||
]);
|
||||
const path = [
|
||||
@@ -105,7 +112,7 @@ class DiscussionNodeHandler extends DiscussionHandler {
|
||||
['discussion_main', 'discussion_main'],
|
||||
[this.vnode.title, null, true],
|
||||
];
|
||||
const vndict = { [typeMapper[type]]: { [name]: this.vnode } };
|
||||
const vndict = { [typeMapper[type]]: { [name.toString()]: this.vnode } };
|
||||
this.response.template = 'discussion_main_or_node.html';
|
||||
this.response.body = {
|
||||
ddocs,
|
||||
@@ -138,11 +145,20 @@ class DiscussionCreateHandler extends DiscussionHandler {
|
||||
this.response.body = { path, vnode: this.vnode };
|
||||
}
|
||||
|
||||
async post({
|
||||
domainId, type, name, title, content, highlight,
|
||||
}) {
|
||||
@param('type', Types.String)
|
||||
@param('name', Types.String)
|
||||
@param('title', Types.String, isTitle)
|
||||
@param('content', Types.String, isContent)
|
||||
@param('highlight', Types.Boolean, true)
|
||||
async post(
|
||||
domainId: string, type: string, _name: string,
|
||||
title: string, content: string, highlight = false,
|
||||
) {
|
||||
this.limitRate('add_discussion', 3600, 30);
|
||||
if (ObjectID.isValid(name)) name = new ObjectID(name);
|
||||
let name: ObjectID | string | number;
|
||||
if (ObjectID.isValid(_name)) name = new ObjectID(_name);
|
||||
else if (isSafeInteger(parseInt(_name, 10))) name = parseInt(_name, 10);
|
||||
else name = _name;
|
||||
if (highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
|
||||
const did = await discussion.add(
|
||||
domainId, typeMapper[type], name, this.user._id,
|
||||
|
||||
+18
-5
@@ -1,4 +1,5 @@
|
||||
import yaml from 'js-yaml';
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { parseTimeMS, parseMemoryMB } from '../utils';
|
||||
import * as record from '../model/record';
|
||||
import * as problem from '../model/problem';
|
||||
@@ -8,7 +9,7 @@ import * as user from '../model/user';
|
||||
import * as task from '../model/task';
|
||||
import * as bus from '../service/bus';
|
||||
import {
|
||||
Route, Handler, Connection, ConnectionHandler,
|
||||
Route, Handler, Connection, ConnectionHandler, Types, param,
|
||||
} from '../service/server';
|
||||
|
||||
async function _postJudge(rdoc) {
|
||||
@@ -36,6 +37,8 @@ async function _postJudge(rdoc) {
|
||||
}
|
||||
|
||||
export async function next(body) {
|
||||
if (body.rid) body.rid = new ObjectID(body.rid);
|
||||
if (body.tid) body.tid = new ObjectID(body.tid);
|
||||
let rdoc = await record.get(body.domainId, body.rid);
|
||||
const $set: any = {};
|
||||
const $push: any = {};
|
||||
@@ -66,6 +69,8 @@ export async function next(body) {
|
||||
}
|
||||
|
||||
export async function end(body) {
|
||||
if (body.rid) body.rid = new ObjectID(body.rid);
|
||||
if (body.tid) body.tid = new ObjectID(body.tid);
|
||||
let rdoc = await record.get(body.domainId, body.rid);
|
||||
const $set: any = {};
|
||||
const $push: any = {};
|
||||
@@ -92,9 +97,17 @@ export async function end(body) {
|
||||
}
|
||||
|
||||
class PretestHandler extends Handler {
|
||||
async post({
|
||||
domainId, pid, code, lang, time = '1s', memory = '256m', input = '',
|
||||
}) {
|
||||
@param('pid', Types.UnsignedInt, true)
|
||||
@param('code', Types.String)
|
||||
@param('lang', Types.String)
|
||||
@param('time', Types.String, true)
|
||||
@param('memory', Types.String, true)
|
||||
@param('input', Types.String, true)
|
||||
async post(
|
||||
domainId: string, pid = 0,
|
||||
code: string, lang: string,
|
||||
time = '1s', memory = '256m', input = '',
|
||||
) {
|
||||
if (pid) {
|
||||
const pdoc = await problem.get(domainId, pid);
|
||||
if (pdoc.config) {
|
||||
@@ -104,7 +117,7 @@ class PretestHandler extends Handler {
|
||||
}
|
||||
}
|
||||
const rid = await record.add(domainId, {
|
||||
pid: pid || String.random(16),
|
||||
pid,
|
||||
uid: this.user._id,
|
||||
type: 'run',
|
||||
time: parseTimeMS(time),
|
||||
|
||||
+18
-18
@@ -403,10 +403,6 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
|
||||
};
|
||||
}
|
||||
|
||||
async post({ domainId, psid }) {
|
||||
if (psid) this.psdoc = await solution.get(domainId, new ObjectID(psid));
|
||||
}
|
||||
|
||||
@param('content', Types.String, isContent)
|
||||
async postSubmit(domainId: string, content: string) {
|
||||
this.checkPerm(PERM.PERM_CREATE_PROBLEM_SOLUTION);
|
||||
@@ -415,17 +411,21 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
|
||||
}
|
||||
|
||||
@param('content', Types.String, isContent)
|
||||
async postEditSolution(domainId: string, content: string) {
|
||||
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION);
|
||||
@param('psid', Types.ObjectID)
|
||||
async postEditSolution(domainId: string, content: string, psid: ObjectID) {
|
||||
let psdoc = await solution.get(domainId, psid);
|
||||
if (psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION);
|
||||
else this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_SELF);
|
||||
const psdoc = await solution.edit(domainId, this.psdoc.docId, content);
|
||||
psdoc = await solution.edit(domainId, this.psdoc.docId, content);
|
||||
this.back({ psdoc });
|
||||
}
|
||||
|
||||
async postDeleteSolution({ domainId }) {
|
||||
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION);
|
||||
@param('psid', Types.ObjectID)
|
||||
async postDeleteSolution(domainId: string, psid: ObjectID) {
|
||||
const psdoc = await solution.get(domainId, psid);
|
||||
if (psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION);
|
||||
else this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_SELF);
|
||||
await solution.del(domainId, this.psdoc.docId);
|
||||
await solution.del(domainId, psdoc.docId);
|
||||
this.back();
|
||||
}
|
||||
|
||||
@@ -471,16 +471,16 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
|
||||
this.back();
|
||||
}
|
||||
|
||||
async postUpvote({ domainId }) {
|
||||
const [psdoc, pssdoc] = await solution.vote(domainId, this.psdoc.docId, this.user._id, 1);
|
||||
this.response.body = { vote: psdoc.vote, user_vote: pssdoc.vote };
|
||||
this.back();
|
||||
@param('psid', Types.ObjectID)
|
||||
async postUpvote(domainId: string, psid: ObjectID) {
|
||||
const [psdoc, pssdoc] = await solution.vote(domainId, psid, this.user._id, 1);
|
||||
this.back({ vote: psdoc.vote, user_vote: pssdoc.vote });
|
||||
}
|
||||
|
||||
async postDownvote({ domainId }) {
|
||||
const [psdoc, pssdoc] = await solution.vote(domainId, this.psdoc.docId, this.user._id, -1);
|
||||
this.response.body = { vote: psdoc.vote, user_vote: pssdoc.vote };
|
||||
this.back();
|
||||
@param('psid', Types.ObjectID)
|
||||
async postDownvote(domainId: string, psid: ObjectID) {
|
||||
const [psdoc, pssdoc] = await solution.vote(domainId, psid, this.user._id, -1);
|
||||
this.back({ vote: psdoc.vote, user_vote: pssdoc.vote });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-8
@@ -1,16 +1,33 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import nunjucks from 'nunjucks';
|
||||
import * as markdown from './markdown';
|
||||
import { STATUS, PERM, PRIV } from '../model/builtin';
|
||||
import * as misc from './misc';
|
||||
|
||||
function Loader() { }
|
||||
Loader.prototype.getSource = function getSource(name) {
|
||||
if (!global.Hydro.template[name]) throw new Error(`Cannot get template ${name}`);
|
||||
return {
|
||||
src: global.Hydro.template[name],
|
||||
path: name,
|
||||
};
|
||||
};
|
||||
class Loader extends nunjucks.Loader {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getSource(name: string) {
|
||||
if (!process.env.debug) {
|
||||
if (!global.Hydro.template[name]) throw new Error(`Cannot get template ${name}`);
|
||||
return {
|
||||
src: global.Hydro.template[name],
|
||||
path: name,
|
||||
noCache: false,
|
||||
};
|
||||
}
|
||||
let fullpath = null;
|
||||
const base = path.join(process.cwd(), 'templates');
|
||||
const p = path.resolve(base, name);
|
||||
if (fs.existsSync(p)) fullpath = p;
|
||||
if (!fullpath) throw new Error(`Cannot get template ${name}`);
|
||||
return {
|
||||
src: fs.readFileSync(fullpath, 'utf-8'),
|
||||
path: fullpath,
|
||||
noCache: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Nunjucks extends nunjucks.Environment {
|
||||
constructor() {
|
||||
|
||||
+7
-2
@@ -4,7 +4,9 @@
|
||||
|
||||
import './interface';
|
||||
import cluster from 'cluster';
|
||||
import { argv } from 'yargs';
|
||||
import parse from 'yargs-parser';
|
||||
|
||||
const argv = parse(process.argv.slice(2));
|
||||
|
||||
global.Hydro = {
|
||||
stat: { reqCount: 0 },
|
||||
@@ -25,7 +27,10 @@ global.Hydro = {
|
||||
};
|
||||
global.onDestory = [];
|
||||
|
||||
if (argv.debug) console.log(process.argv);
|
||||
if (argv.debug) {
|
||||
console.log(process.argv);
|
||||
process.env.debug = 'enable';
|
||||
}
|
||||
|
||||
async function terminate() {
|
||||
for (const task of global.onDestory) {
|
||||
|
||||
+19
-15
@@ -51,7 +51,7 @@ const acm = {
|
||||
if (!j.accept) naccept[j.pid]++;
|
||||
}
|
||||
function _time(jdoc) {
|
||||
const real = jdoc.rid.generationTime - Math.floor(tdoc.begin_at / 1000);
|
||||
const real = jdoc.rid.generationTime - Math.floor(tdoc.beginAt / 1000);
|
||||
const penalty = 20 * 60 * naccept[jdoc.pid];
|
||||
return real + penalty;
|
||||
}
|
||||
@@ -73,23 +73,27 @@ const acm = {
|
||||
{ type: 'solved_problems', value: _('Solved Problems') },
|
||||
];
|
||||
if (isExport) {
|
||||
columns.push({ type: 'total_time', value: _('Total Time (Seconds)') });
|
||||
columns.push({ type: 'total_time_str', value: _('Total Time') });
|
||||
columns.push(
|
||||
{ type: 'total_time', value: _('Total Time (Seconds)') },
|
||||
{ type: 'total_time_str', value: _('Total Time') },
|
||||
);
|
||||
}
|
||||
for (const i in tdoc.pids) {
|
||||
if (isExport) {
|
||||
columns.push({
|
||||
type: 'problem_flag',
|
||||
value: '#{0} {1}'.format(i + 1, pdict[tdoc.pids[i]].title),
|
||||
});
|
||||
columns.push({
|
||||
type: 'problem_time',
|
||||
value: '#{0} {1}'.format(i + 1, _('Time (Seconds)')),
|
||||
});
|
||||
columns.push({
|
||||
type: 'problem_time_str',
|
||||
value: '#{0} {1}'.format(i + 1, _('Time')),
|
||||
});
|
||||
columns.push(
|
||||
{
|
||||
type: 'problem_flag',
|
||||
value: '#{0} {1}'.format(i + 1, pdict[tdoc.pids[i]].title),
|
||||
},
|
||||
{
|
||||
type: 'problem_time',
|
||||
value: '#{0} {1}'.format(i + 1, _('Time (Seconds)')),
|
||||
},
|
||||
{
|
||||
type: 'problem_time_str',
|
||||
value: '#{0} {1}'.format(i + 1, _('Time')),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
columns.push({
|
||||
type: 'problem_detail',
|
||||
|
||||
@@ -15,7 +15,7 @@ export const typeDisplay = {
|
||||
};
|
||||
|
||||
export function add(
|
||||
domainId: string, parentType: number, parentId: ObjectID,
|
||||
domainId: string, parentType: number, parentId: ObjectID | number | string,
|
||||
owner: number, title: string, content: string,
|
||||
ip: string | null = null, highlight: boolean = false,
|
||||
) {
|
||||
|
||||
+6
-7
@@ -28,20 +28,19 @@ export function del(_id: ObjectID) {
|
||||
export async function getFirst(query: any) {
|
||||
const q = { ...query };
|
||||
q.executeAfter = q.executeAfter || { $lt: new Date().getTime() };
|
||||
const res = await coll.find(q).sort('_id', 1).limit(1).toArray();
|
||||
if (res.length) {
|
||||
await coll.deleteOne({ _id: res[0]._id });
|
||||
if (res[0].interval) {
|
||||
const res = await coll.findOneAndDelete(q);
|
||||
if (res.value) {
|
||||
if (res.value.interval) {
|
||||
await coll.insertOne({
|
||||
...res[0], executeAfter: moment().add(...res[0].interval).toDate(),
|
||||
...res.value, executeAfter: moment().add(...res.value.interval).toDate(),
|
||||
});
|
||||
}
|
||||
return res[0];
|
||||
return res.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function consume(query, cb: Function) {
|
||||
export async function consume(query: any, cb: Function) {
|
||||
let isRunning = false;
|
||||
const interval = setInterval(async () => {
|
||||
if (isRunning) return;
|
||||
|
||||
Reference in new issue
Block a user