From e39a5fa87f6fb1838ae1ef49fab6dbb449b65b87 Mon Sep 17 00:00:00 2001 From: undefined Date: Thu, 18 Jun 2026 12:59:55 +0000 Subject: [PATCH] core&ui: cache uicontext.domain --- packages/hydrooj/src/handler/domain.ts | 4 ++ packages/hydrooj/src/model/domain.ts | 17 +++++++- packages/hydrooj/src/service/layers/base.ts | 3 +- packages/ui-default/pages/domain_user.page.js | 4 +- packages/ui-default/pages/record_main.page.ts | 7 +++- .../ui-default/templates/partials/nav.html | 2 +- packages/ui-default/utils/db.ts | 3 +- packages/ui-default/utils/index.ts | 41 ++++++++++++++++++- 8 files changed, 71 insertions(+), 10 deletions(-) diff --git a/packages/hydrooj/src/handler/domain.ts b/packages/hydrooj/src/handler/domain.ts index ee65ddd2d..40fc1f373 100644 --- a/packages/hydrooj/src/handler/domain.ts +++ b/packages/hydrooj/src/handler/domain.ts @@ -436,6 +436,10 @@ export const DomainApi = { return ddoc; }, ), + 'domain.current': Query( + Schema.object({}), + async (handler) => ({ domain: handler.domain as DomainDoc }), + ), groups: Query( Schema.object({ domainId: Schema.string().required(), diff --git a/packages/hydrooj/src/model/domain.ts b/packages/hydrooj/src/model/domain.ts index 0aaa2f8ed..db060092b 100644 --- a/packages/hydrooj/src/model/domain.ts +++ b/packages/hydrooj/src/model/domain.ts @@ -13,6 +13,18 @@ import UserModel, { deleteUserCache } from './user'; const coll = db.collection('domain'); const collUser = db.collection('domain.user'); const cache = new LRUCache({ max: 1000, ttl: 300 * 1000 }); +const cacheVersion = Symbol('domainCacheVersion'); + +function setCache(key: string, ddoc: DomainDoc | null) { + if (ddoc) { + Object.defineProperty(ddoc, cacheVersion, { + value: Date.now(), + enumerable: false, + configurable: true, + }); + } + cache.set(key, ddoc); +} interface DomainUserArg { _id: number; @@ -22,6 +34,7 @@ interface DomainUserArg { class DomainModel { static coll = coll; static collUser = collUser; + static getVersion = (ddoc) => ddoc ? ddoc[cacheVersion] : null; static JOIN_METHOD_NONE = 0; static JOIN_METHOD_ALL = 1; @@ -73,7 +86,7 @@ class DomainModel { const result = await coll.findOne(query); if (result) { await bus.parallel('domain/get', result); - cache.set(key, result); + setCache(key, result); } return result; } @@ -88,7 +101,7 @@ class DomainModel { const result = await coll.findOne(query); if (result) { await bus.parallel('domain/get', result); - cache.set(key, result); + setCache(key, result); } else { cache.set(key, null); } diff --git a/packages/hydrooj/src/service/layers/base.ts b/packages/hydrooj/src/service/layers/base.ts index 6f13f03bf..a8edce4ea 100644 --- a/packages/hydrooj/src/service/layers/base.ts +++ b/packages/hydrooj/src/service/layers/base.ts @@ -3,6 +3,7 @@ import { cloneDeep, omit } from 'lodash'; import type { KoaContext } from '@hydrooj/framework'; import { randomPick, Time } from '@hydrooj/utils'; import { PERM } from '../../model/builtin'; +import domain from '../../model/domain'; import system from '../../model/system'; import token from '../../model/token'; @@ -34,7 +35,7 @@ export default async (ctx: KoaContext, next: Next) => { UiContext.cdn_dynamic = system.get('server.cdn_dynamic'); } UiContext.domainId = domainId; - UiContext.domain = domainInfo; + UiContext.domainVersion = domain.getVersion(domainInfo); ctx.HydroContext.UiContext = UiContext; ctx.HydroContext.domain = domainInfo; ctx.HydroContext.args = args; diff --git a/packages/ui-default/pages/domain_user.page.js b/packages/ui-default/pages/domain_user.page.js index 4c6351ff7..2939f9181 100644 --- a/packages/ui-default/pages/domain_user.page.js +++ b/packages/ui-default/pages/domain_user.page.js @@ -17,7 +17,7 @@ const page = new NamedPage('domain_user', () => {

${i18n('Users will have to manually join the domain first before selected roles can be applied.')}

${i18n('To join the domain, users can click the "Join Domain" button on "My Domain" page.')}

${i18n('Or use the following link:')}

-

/domain/join?target=${UiContext.domain._id}

+

/domain/join?target=${UiContext.domainId}

`, }).open(); }); @@ -37,7 +37,7 @@ const page = new NamedPage('domain_user', () => { label: 'Role', options: UiContext.roles.filter((i) => !['default', 'guest'].includes(i)), }, - ...((UiContext.canForceJoin && UiContext.domain._id !== 'system') ? { + ...((UiContext.canForceJoin && UiContext.domainId !== 'system') ? { join: { type: 'checkbox', label: i18n('Mark user as joined using admin privilege'), diff --git a/packages/ui-default/pages/record_main.page.ts b/packages/ui-default/pages/record_main.page.ts index f5badd3fb..154c08896 100644 --- a/packages/ui-default/pages/record_main.page.ts +++ b/packages/ui-default/pages/record_main.page.ts @@ -3,7 +3,9 @@ import ProblemSelectAutoComplete from 'vj/components/autocomplete/ProblemSelectA import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete'; import Notification from 'vj/components/notification'; import { NamedPage } from 'vj/misc/Page'; -import { getAvailableLangs, request, tpl } from 'vj/utils'; +import { + getAvailableLangs, getDomainInfo, request, tpl, +} from 'vj/utils'; const page = new NamedPage('record_main', async () => { const [{ default: WebSocket }, { DiffDOM }] = await Promise.all([ @@ -37,7 +39,8 @@ const page = new NamedPage('record_main', async () => { ProblemSelectAutoComplete.getOrConstruct($('[name="pid"]'), { clearDefaultValue: false, }); - const langs = UiContext.domain.langs?.split(',').map((i) => i.trim()).filter((i) => i); + const domain = await getDomainInfo(); + const langs = domain.langs?.split(',').map((i) => i.trim()).filter((i) => i); const availableLangs = getAvailableLangs(langs?.length ? langs : undefined); Object.keys(availableLangs).map( (i) => ($('select[name="lang"]').append(tpl``))); diff --git a/packages/ui-default/templates/partials/nav.html b/packages/ui-default/templates/partials/nav.html index c71be3926..c0af0e2a8 100644 --- a/packages/ui-default/templates/partials/nav.html +++ b/packages/ui-default/templates/partials/nav.html @@ -35,7 +35,7 @@ {% else %} {% if model.system.get('ui-default.domainNavigation') %}