core: bug fixes

This commit is contained in:
undefined committed 2025-03-16 01:11:03 +08:00
1 parent aa75195250
commit e0628c6197
4 files changed
+37 -28

No files matched your search

+29 -19
View File
@@ -550,7 +550,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
} }
} }
private async handleWS(ctx: KoaContext, HandlerClass, checker, conn, layer?) { private async handleWS(ctx: KoaContext, HandlerClass, checker, conn?, layer?) {
const { args } = ctx.HydroContext; const { args } = ctx.HydroContext;
const h = new HandlerClass(ctx, this.ctx); const h = new HandlerClass(ctx, this.ctx);
// FIXME: should pass type check // FIXME: should pass type check
@@ -581,6 +581,23 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
ctx.handler = h; ctx.handler = h;
h.conn = conn; h.conn = conn;
const disposables = []; const disposables = [];
let interval: NodeJS.Timeout;
let closed = false;
const clean = async (err?: Error) => {
if (closed) return;
closed = true;
if (err) await h.onerror(err);
// FIXME: should pass type check
else (this.ctx.emit as any)('connection/close', h);
h.active = false;
for (const d of disposables) d();
if (layer) layer.clients.delete(conn);
if (err && !layer) ctx.status = 500;
if (interval) clearInterval(interval);
h.cleanup?.(args);
};
try { try {
// FIXME: should pass type check // FIXME: should pass type check
await (this.ctx.parallel as any)('handler/create', h, 'ws'); await (this.ctx.parallel as any)('handler/create', h, 'ws');
@@ -591,18 +608,6 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
if (h.prepare) await h.prepare(args); if (h.prepare) await h.prepare(args);
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
for (const { name, target } of h.__subscribe || []) disposables.push(this.ctx.on(name, target.bind(h))); for (const { name, target } of h.__subscribe || []) disposables.push(this.ctx.on(name, target.bind(h)));
let closed = false;
let interval: NodeJS.Timeout;
const clean = () => {
if (closed) return;
closed = true;
// FIXME: should pass type check
(this.ctx.emit as any)('connection/close', h);
if (layer) layer.clients.delete(conn);
if (interval) clearInterval(interval);
for (const d of disposables) d();
h.cleanup?.(args);
};
if (layer) { if (layer) {
let lastHeartbeat = Date.now(); let lastHeartbeat = Date.now();
interval = setInterval(() => { interval = setInterval(() => {
@@ -615,7 +620,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
conn.on('pong', () => { conn.on('pong', () => {
lastHeartbeat = Date.now(); lastHeartbeat = Date.now();
}); });
conn.onmessage = (e) => { conn.onmessage = async (e) => {
lastHeartbeat = Date.now(); lastHeartbeat = Date.now();
if (e.data === 'pong') return; if (e.data === 'pong') return;
if (e.data === 'ping') { if (e.data === 'ping') {
@@ -629,7 +634,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
conn.close(); conn.close();
} }
try { try {
h.message?.(payload); await h.message?.(payload);
} catch (err) { } catch (err) {
logger.error(e); logger.error(e);
} }
@@ -637,15 +642,20 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
} else ctx.body = stream; } else ctx.body = stream;
// FIXME: should pass type check // FIXME: should pass type check
await (this.ctx.parallel as any)('connection/active', h as any); await (this.ctx.parallel as any)('connection/active', h as any);
h.active = true;
if (layer) { if (layer) {
if (conn.readyState === conn.OPEN) { if (conn.readyState === conn.OPEN) {
conn.on('close', clean); conn.on('close', () => clean());
conn.on('error', (err) => clean(err));
conn.resume(); conn.resume();
} else clean(); } else clean();
} else stream.on('close', clean); } else {
stream.on('close', () => clean());
stream.on('error', (err) => clean(err));
}
} catch (e) { } catch (e) {
await h.onerror(e); // error during initialization (prepare, hooks)
if (!layer) ctx.status = 500; await clean(e);
} }
} }
+3 -3
View File
@@ -183,7 +183,7 @@ class SystemConfigHandler extends SystemHandler {
@requireSudo @requireSudo
async get() { async get() {
this.response.template = 'manage_config.html'; this.response.template = 'manage_config.html';
let value = this.ctx.config.configSource; let value;
const processNode = (node: any, schema: Schema<any, any>, parent?: any, accessKey?: string) => { const processNode = (node: any, schema: Schema<any, any>, parent?: any, accessKey?: string) => {
if (['union', 'intersect'].includes(schema.type)) { if (['union', 'intersect'].includes(schema.type)) {
@@ -199,7 +199,7 @@ class SystemConfigHandler extends SystemHandler {
}; };
try { try {
value = Schema.intersect(this.ctx.config.settings)(yaml.load(value)); value = Schema.intersect(this.ctx.config.settings)(yaml.load(this.ctx.config.configSource));
for (const schema of this.ctx.config.settings) processNode(value, schema); for (const schema of this.ctx.config.settings) processNode(value, schema);
} catch (e) { } } catch (e) { }
this.response.body = { this.response.body = {
@@ -218,7 +218,7 @@ class SystemConfigHandler extends SystemHandler {
for (const item of schema.list) processNode(node, old, item, parent, accessKey); for (const item of schema.list) processNode(node, old, item, parent, accessKey);
} }
if (parent && (schema.meta.secret === true || schema.meta.role === 'secret')) { if (parent && (schema.meta.secret === true || schema.meta.role === 'secret')) {
if (node === '[hidden]') parent[accessKey] = old[accessKey]; if (node === '[hidden]') parent[accessKey] = old;
// TODO support more types // TODO support more types
} }
if (schema.type === 'object') { if (schema.type === 'object') {
+3 -4
View File
@@ -291,9 +291,8 @@ const oi = buildContestRule({
continue; continue;
} }
if (!detail[j.pid] || detail[j.pid].score < j.score || this.submitAfterAccept) { if (!detail[j.pid] || detail[j.pid].score < j.score || this.submitAfterAccept) {
detail[j.pid] = j; detail[j.pid] = { ...j };
display[j.pid] ||= {}; display[j.pid] = { ...j };
display[j.pid] = j;
} }
} }
for (const i in display) { for (const i in display) {
@@ -360,7 +359,7 @@ const oi = buildContestRule({
accepted[s.pid] = true; accepted[s.pid] = true;
} }
} }
const tsddict = (config.lockAt ? tsdoc.display : tsdoc.detail) || {}; const tsddict = ((config.lockAt && isLocked(tdoc, new Date())) ? tsdoc.display : tsdoc.detail) || {};
for (const pid of tdoc.pids) { for (const pid of tdoc.pids) {
const index = `${tsdoc.uid}/${tdoc.domainId}/${pid}`; const index = `${tsdoc.uid}/${tdoc.domainId}/${pid}`;
// eslint-disable-next-line @typescript-eslint/no-use-before-define // eslint-disable-next-line @typescript-eslint/no-use-before-define
+2 -2
View File
@@ -158,11 +158,11 @@ export default class HMR extends Service {
for (const filename in require.cache) { for (const filename in require.cache) {
const module = require.cache[filename]; const module = require.cache[filename];
const plugin = unwrapExports(module.exports); const plugin = unwrapExports(module.exports);
if (typeof plugin !== 'object' || !plugin || !('apply' in plugin)) continue; if (!plugin) continue;
const runtime = this.ctx.registry.get(plugin); const runtime = this.ctx.registry.get(plugin);
if (!runtime || this.declined.has(filename)) continue; if (!runtime || this.declined.has(filename)) continue;
pending.set(filename, plugin); pending.set(filename, plugin);
if (!plugin || !('sideEffect' in plugin) || !plugin['sideEffect']) this.declined.add(filename); if (!plugin?.sideEffect) this.declined.add(filename);
} }
for (const [filename, plugin] of pending) { for (const [filename, plugin] of pending) {