FoundKey/packages/backend/src/services/user-cache.ts

71 lines
2.3 KiB
TypeScript

import { IsNull } from 'typeorm';
import { ILocalUser, User } from '@/models/entities/user.js';
import { Users } from '@/models/index.js';
import { Cache } from '@/misc/cache.js';
import { subscriber } from '@/db/redis.js';
import { MINUTE } from '@/const.js';
export const userByIdCache = new Cache<User>(
15 * MINUTE,
async (id) => await Users.findOneBy({ id, isDeleted: IsNull() }) ?? undefined,
);
export const localUserByNativeTokenCache = new Cache<ILocalUser>(
15 * MINUTE,
async (token) => await Users.findOneBy({ token, host: IsNull(), isDeleted: IsNull() }) as ILocalUser | null ?? undefined,
);
export const uriPersonCache = new Cache<User>(
15 * MINUTE,
async (uri) => await Users.findOneBy({ uri, isDeleted: IsNull() }) ?? undefined,
);
export const publicKeyCache = new Cache<UserPublickey>(
2 * HOUR,
(keyId) => UserPublickeys.findOneBy({ keyId }).then(x => x ?? undefined),
);
export const publicKeyByUserIdCache = new Cache<UserPublickey>(
2 * HOUR,
(userId) => UserPublickeys.findOneBy({ userId }).then(x => x ?? undefined),
);
subscriber.on('message', async (_, data) => {
const obj = JSON.parse(data);
if (obj.channel === 'internal') {
const { type, body } = obj.message;
switch (type) {
case 'userChangeSuspendedState':
case 'userChangeSilencedState':
case 'userChangeModeratorState':
case 'remoteUserUpdated': {
const user = await Users.findOneByOrFail({ id: body.id });
if (user.isDeleted) {
userByIdCache.delete(user.id);
uriPersonCache.delete(user.uri);
if (Users.isLocalUser(user)) {
localUserByNativeTokenCache.delete(user.token);
}
// using get here because it does not fetch from the database
const publicKey = publicKeyByUserIdCache.get(user.id);
if (publicKey != null) {
publicKeyByUserIdCache.delete(user.id);
publicKeyCache.delete(publicKey.keyId);
}
} else {
userByIdCache.set(user.id, user);
uriPersonCache.set(user.uri, user);
if (Users.isLocalUser(user)) {
localUserByNativeTokenCache.set(user.token, user);
}
}
break;
}
case 'userTokenRegenerated': {
const user = await Users.findOneByOrFail({ id: body.id }) as ILocalUser;
localUserByNativeTokenCache.delete(body.oldToken);
localUserByNativeTokenCache.set(body.newToken, user);
break;
}
}
}
});