mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: multi-worker user cache
This commit is contained in:
1 parent
81c1e0cfd8
commit
a908252c57
4 files changed
+19
-15
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.32.6",
|
"version": "2.32.7",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
|
|||||||
@@ -104,8 +104,11 @@ export async function get(domainId: string, tid: ObjectID) {
|
|||||||
return tdoc;
|
return tdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getMulti = (domainId: string, query: FilterQuery<TrainingDoc> = {}) =>
|
||||||
|
document.getMulti(domainId, document.TYPE_TRAINING, query).sort({ pin: -1, _id: -1 });
|
||||||
|
|
||||||
export async function getList(domainId: string, tids: ObjectID[]) {
|
export async function getList(domainId: string, tids: ObjectID[]) {
|
||||||
const tdocs = await this.getMulti(
|
const tdocs = await getMulti(
|
||||||
domainId, { _id: { $in: Array.from(new Set(tids)) } },
|
domainId, { _id: { $in: Array.from(new Set(tids)) } },
|
||||||
).toArray();
|
).toArray();
|
||||||
const r = {};
|
const r = {};
|
||||||
@@ -113,9 +116,6 @@ export async function getList(domainId: string, tids: ObjectID[]) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getMulti = (domainId: string, query: FilterQuery<TrainingDoc> = {}) =>
|
|
||||||
document.getMulti(domainId, document.TYPE_TRAINING, query).sort({ pin: -1, _id: -1 });
|
|
||||||
|
|
||||||
global.Hydro.model.training = {
|
global.Hydro.model.training = {
|
||||||
getPids,
|
getPids,
|
||||||
isDone,
|
isDone,
|
||||||
|
|||||||
@@ -21,18 +21,21 @@ const coll: Collection<Udoc> = db.collection('user');
|
|||||||
const logger = new Logger('model/user');
|
const logger = new Logger('model/user');
|
||||||
const cache = new LRU<string, User>({ max: 500, maxAge: 300 * 1000 });
|
const cache = new LRU<string, User>({ max: 500, maxAge: 300 * 1000 });
|
||||||
|
|
||||||
export function deleteUserCache(udoc: User | Udoc | string) {
|
export function deleteUserCache(udoc: User | Udoc | string | undefined | null) {
|
||||||
|
if (!udoc) return;
|
||||||
|
bus.broadcast('user/delcache', JSON.stringify(udoc));
|
||||||
if (typeof udoc === 'string') {
|
if (typeof udoc === 'string') {
|
||||||
for (const key of cache.keys().filter((k) => k.endsWith(`/${udoc}`))) {
|
for (const key of cache.keys().filter((k) => k.endsWith(`/${udoc}`))) {
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
}
|
}
|
||||||
} else if (udoc) {
|
} else {
|
||||||
const id = [udoc._id.toString(), udoc.uname.toLowerCase(), udoc.mail.toLowerCase()];
|
const id = [udoc._id.toString(), udoc.uname.toLowerCase(), udoc.mail.toLowerCase()];
|
||||||
for (const key of cache.keys().filter((k) => id.includes(k.split('/')[0]))) {
|
for (const key of cache.keys().filter((k) => id.includes(k.split('/')[0]))) {
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bus.on('user/delcache', (content) => deleteUserCache(JSON.parse(content)));
|
||||||
|
|
||||||
class User implements _User {
|
class User implements _User {
|
||||||
_id: number;
|
_id: number;
|
||||||
@@ -145,7 +148,7 @@ class UserModel {
|
|||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async getById(domainId: string, _id: number, scope: bigint | string = PERM.PERM_ALL): Promise<User | null> {
|
static async getById(domainId: string, _id: number, scope: bigint | string = PERM.PERM_ALL): Promise<User | null> {
|
||||||
if (cache.has(`${_id}/${domainId}`)) return cache.get(`${_id}/${domainId}`);
|
if (cache.has(`${_id}/${domainId}`)) return cache.get(`${_id}/${domainId}`) || null;
|
||||||
const udoc = await coll.findOne({ _id });
|
const udoc = await coll.findOne({ _id });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
@@ -159,16 +162,16 @@ class UserModel {
|
|||||||
|
|
||||||
static async getList(domainId: string, uids: number[]): Promise<Udict> {
|
static async getList(domainId: string, uids: number[]): Promise<Udict> {
|
||||||
const _uids = new Set(uids);
|
const _uids = new Set(uids);
|
||||||
const r = {};
|
const r: Udict = {};
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
for (const uid of _uids) r[uid] = (await UserModel.getById(domainId, uid)) || UserModel.defaultUser;
|
for (const uid of _uids) r[uid] = (await UserModel.getById(domainId, uid)) || new User(UserModel.defaultUser, {});
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async getByUname(domainId: string, uname: string): Promise<User | null> {
|
static async getByUname(domainId: string, uname: string): Promise<User | null> {
|
||||||
const unameLower = uname.trim().toLowerCase();
|
const unameLower = uname.trim().toLowerCase();
|
||||||
if (cache.has(`${unameLower}/${domainId}`)) return cache.get(`${unameLower}/${domainId}`);
|
if (cache.has(`${unameLower}/${domainId}`)) return cache.get(`${unameLower}/${domainId}`) || null;
|
||||||
const udoc = await coll.findOne({ unameLower });
|
const udoc = await coll.findOne({ unameLower });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
@@ -182,7 +185,7 @@ class UserModel {
|
|||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async getByEmail(domainId: string, mail: string): Promise<User | null> {
|
static async getByEmail(domainId: string, mail: string): Promise<User | null> {
|
||||||
const mailLower = mail.trim().toLowerCase();
|
const mailLower = mail.trim().toLowerCase();
|
||||||
if (cache.has(`${mailLower}/${domainId}`)) return cache.get(`${mailLower}/${domainId}`);
|
if (cache.has(`${mailLower}/${domainId}`)) return cache.get(`${mailLower}/${domainId}`) || null;
|
||||||
const udoc = await coll.findOne({ mailLower });
|
const udoc = await coll.findOne({ mailLower });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
@@ -209,7 +212,7 @@ class UserModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async setPassword(uid: number, password: string): Promise<Udoc> {
|
static async setPassword(uid: number, password: string): Promise<Udoc | null> {
|
||||||
const salt = String.random();
|
const salt = String.random();
|
||||||
const res = await coll.findOneAndUpdate(
|
const res = await coll.findOneAndUpdate(
|
||||||
{ _id: uid },
|
{ _id: uid },
|
||||||
@@ -217,7 +220,7 @@ class UserModel {
|
|||||||
{ returnDocument: 'after' },
|
{ returnDocument: 'after' },
|
||||||
);
|
);
|
||||||
deleteUserCache(res.value);
|
deleteUserCache(res.value);
|
||||||
return res.value;
|
return res.value || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
@@ -300,7 +303,7 @@ class UserModel {
|
|||||||
{ returnDocument: 'after' },
|
{ returnDocument: 'after' },
|
||||||
);
|
);
|
||||||
deleteUserCache(res.value);
|
deleteUserCache(res.value);
|
||||||
return res.value;
|
return res.value || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export interface EventMap extends Record<string, any> {
|
|||||||
|
|
||||||
'user/message': (uid: number, mdoc: MessageDoc) => void
|
'user/message': (uid: number, mdoc: MessageDoc) => void
|
||||||
'user/get': (udoc: User) => void
|
'user/get': (udoc: User) => void
|
||||||
|
'user/delcache': (content: string) => void
|
||||||
|
|
||||||
'domain/create': (ddoc: DomainDoc) => VoidReturn
|
'domain/create': (ddoc: DomainDoc) => VoidReturn
|
||||||
'domain/before-get': (query: FilterQuery<DomainDoc>) => VoidReturn
|
'domain/before-get': (query: FilterQuery<DomainDoc>) => VoidReturn
|
||||||
|
|||||||
Reference in new issue
Block a user