parent
55c80db66d
commit
bc3234510c
|
@ -20,6 +20,7 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null>;
|
public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null>;
|
||||||
public localUserByIdCache: MemoryKVCache<MiLocalUser>;
|
public localUserByIdCache: MemoryKVCache<MiLocalUser>;
|
||||||
public uriPersonCache: MemoryKVCache<MiUser | null>;
|
public uriPersonCache: MemoryKVCache<MiUser | null>;
|
||||||
|
public userProfileCache: RedisKVCache<MiUserProfile>;
|
||||||
public userMutingsCache: RedisKVCache<Set<string>>;
|
public userMutingsCache: RedisKVCache<Set<string>>;
|
||||||
public userBlockingCache: RedisKVCache<Set<string>>;
|
public userBlockingCache: RedisKVCache<Set<string>>;
|
||||||
public userBlockedCache: RedisKVCache<Set<string>>; // NOTE: 「被」Blockキャッシュ
|
public userBlockedCache: RedisKVCache<Set<string>>; // NOTE: 「被」Blockキャッシュ
|
||||||
|
@ -36,6 +37,9 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@Inject(DI.userProfilesRepository)
|
||||||
|
private userProfilesRepository: UserProfilesRepository,
|
||||||
|
|
||||||
@Inject(DI.mutingsRepository)
|
@Inject(DI.mutingsRepository)
|
||||||
private mutingsRepository: MutingsRepository,
|
private mutingsRepository: MutingsRepository,
|
||||||
|
|
||||||
|
@ -57,6 +61,14 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
this.localUserByIdCache = new MemoryKVCache<MiLocalUser>(Infinity);
|
this.localUserByIdCache = new MemoryKVCache<MiLocalUser>(Infinity);
|
||||||
this.uriPersonCache = new MemoryKVCache<MiUser | null>(Infinity);
|
this.uriPersonCache = new MemoryKVCache<MiUser | null>(Infinity);
|
||||||
|
|
||||||
|
this.userProfileCache = new RedisKVCache<MiUserProfile>(this.redisClient, 'userProfile', {
|
||||||
|
lifetime: 1000 * 60 * 30, // 30m
|
||||||
|
memoryCacheLifetime: 1000 * 60, // 1m
|
||||||
|
fetcher: (key) => this.userProfilesRepository.findOneByOrFail({ userId: key }),
|
||||||
|
toRedisConverter: (value) => JSON.stringify(value),
|
||||||
|
fromRedisConverter: (value) => JSON.parse(value), // TODO: date型の考慮
|
||||||
|
});
|
||||||
|
|
||||||
this.userMutingsCache = new RedisKVCache<Set<string>>(this.redisClient, 'userMutings', {
|
this.userMutingsCache = new RedisKVCache<Set<string>>(this.redisClient, 'userMutings', {
|
||||||
lifetime: 1000 * 60 * 30, // 30m
|
lifetime: 1000 * 60 * 30, // 30m
|
||||||
memoryCacheLifetime: 1000 * 60, // 1m
|
memoryCacheLifetime: 1000 * 60, // 1m
|
||||||
|
@ -174,6 +186,7 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
this.localUserByNativeTokenCache.dispose();
|
this.localUserByNativeTokenCache.dispose();
|
||||||
this.localUserByIdCache.dispose();
|
this.localUserByIdCache.dispose();
|
||||||
this.uriPersonCache.dispose();
|
this.uriPersonCache.dispose();
|
||||||
|
this.userProfileCache.dispose();
|
||||||
this.userMutingsCache.dispose();
|
this.userMutingsCache.dispose();
|
||||||
this.userBlockingCache.dispose();
|
this.userBlockingCache.dispose();
|
||||||
this.userBlockedCache.dispose();
|
this.userBlockedCache.dispose();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { bindThis } from '@/decorators.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { Packed } from '@/misc/json-schema.js';
|
import { Packed } from '@/misc/json-schema.js';
|
||||||
import type { NotesRepository, UserProfilesRepository } from '@/models/_.js';
|
import type { NotesRepository } from '@/models/_.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
|
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
|
||||||
import { isUserRelated } from '@/misc/is-user-related.js';
|
import { isUserRelated } from '@/misc/is-user-related.js';
|
||||||
|
@ -41,8 +41,6 @@ export class FanoutTimelineEndpointService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.notesRepository)
|
@Inject(DI.notesRepository)
|
||||||
private notesRepository: NotesRepository,
|
private notesRepository: NotesRepository,
|
||||||
@Inject(DI.userProfilesRepository)
|
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
|
||||||
|
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
private cacheService: CacheService,
|
private cacheService: CacheService,
|
||||||
|
@ -111,7 +109,7 @@ export class FanoutTimelineEndpointService {
|
||||||
this.cacheService.userMutingsCache.fetch(ps.me.id),
|
this.cacheService.userMutingsCache.fetch(ps.me.id),
|
||||||
this.cacheService.renoteMutingsCache.fetch(ps.me.id),
|
this.cacheService.renoteMutingsCache.fetch(ps.me.id),
|
||||||
this.cacheService.userBlockedCache.fetch(ps.me.id),
|
this.cacheService.userBlockedCache.fetch(ps.me.id),
|
||||||
(await this.userProfilesRepository.findOneByOrFail({ userId: me.id }).then(p => new Set(p.mutedInstances))),
|
this.cacheService.userProfileCache.fetch(me.id).then(p => new Set(p.mutedInstances)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const parentFilter = filter;
|
const parentFilter = filter;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import * as Redis from 'ioredis';
|
||||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { UserProfilesRepository, UsersRepository } from '@/models/_.js';
|
import type { UsersRepository } from '@/models/_.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiNotification } from '@/models/Notification.js';
|
import type { MiNotification } from '@/models/Notification.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -36,9 +36,6 @@ export class NotificationService implements OnApplicationShutdown {
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
@Inject(DI.userProfilesRepository)
|
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
|
||||||
|
|
||||||
private notificationEntityService: NotificationEntityService,
|
private notificationEntityService: NotificationEntityService,
|
||||||
private idService: IdService,
|
private idService: IdService,
|
||||||
private globalEventService: GlobalEventService,
|
private globalEventService: GlobalEventService,
|
||||||
|
@ -95,7 +92,7 @@ export class NotificationService implements OnApplicationShutdown {
|
||||||
data: Omit<FilterUnionByProperty<MiNotification, 'type', T>, 'type' | 'id' | 'createdAt' | 'notifierId'>,
|
data: Omit<FilterUnionByProperty<MiNotification, 'type', T>, 'type' | 'id' | 'createdAt' | 'notifierId'>,
|
||||||
notifierId?: MiUser['id'] | null,
|
notifierId?: MiUser['id'] | null,
|
||||||
): Promise<MiNotification | null> {
|
): Promise<MiNotification | null> {
|
||||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: notifieeId });
|
const profile = await this.cacheService.userProfileCache.fetch(notifieeId);
|
||||||
|
|
||||||
// 古いMisskeyバージョンのキャッシュが残っている可能性がある
|
// 古いMisskeyバージョンのキャッシュが残っている可能性がある
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
|
|
@ -7,13 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { ModuleRef } from '@nestjs/core';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type {
|
import type { FollowRequestsRepository, NotesRepository, MiUser, UsersRepository } from '@/models/_.js';
|
||||||
FollowRequestsRepository,
|
|
||||||
NotesRepository,
|
|
||||||
MiUser,
|
|
||||||
UsersRepository,
|
|
||||||
UserProfilesRepository,
|
|
||||||
} from '@/models/_.js';
|
|
||||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||||
import type { MiGroupedNotification, MiNotification } from '@/models/Notification.js';
|
import type { MiGroupedNotification, MiNotification } from '@/models/Notification.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
|
@ -48,8 +42,7 @@ export class NotificationEntityService implements OnModuleInit {
|
||||||
private followRequestsRepository: FollowRequestsRepository,
|
private followRequestsRepository: FollowRequestsRepository,
|
||||||
|
|
||||||
private cacheService: CacheService,
|
private cacheService: CacheService,
|
||||||
@Inject(DI.userProfilesRepository)
|
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
|
||||||
//private userEntityService: UserEntityService,
|
//private userEntityService: UserEntityService,
|
||||||
//private noteEntityService: NoteEntityService,
|
//private noteEntityService: NoteEntityService,
|
||||||
) {
|
) {
|
||||||
|
@ -309,7 +302,7 @@ export class NotificationEntityService implements OnModuleInit {
|
||||||
userMutedInstances,
|
userMutedInstances,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
this.cacheService.userMutingsCache.fetch(meId),
|
this.cacheService.userMutingsCache.fetch(meId),
|
||||||
await this.userProfilesRepository.findOneByOrFail({ userId: meId }).then(p => new Set(p.mutedInstances)),
|
this.cacheService.userProfileCache.fetch(meId).then(p => new Set(p.mutedInstances)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const notifierIds = notifications.map(notification => 'notifierId' in notification ? notification.notifierId : null).filter(isNotNull);
|
const notifierIds = notifications.map(notification => 'notifierId' in notification ? notification.notifierId : null).filter(isNotNull);
|
||||||
|
|
|
@ -477,6 +477,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
|
|
||||||
const updatedProfile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
|
const updatedProfile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
|
await this.cacheService.userProfileCache.set(user.id, updatedProfile);
|
||||||
|
|
||||||
// Publish meUpdated event
|
// Publish meUpdated event
|
||||||
this.globalEventService.publishMainStream(user.id, 'meUpdated', iObj);
|
this.globalEventService.publishMainStream(user.id, 'meUpdated', iObj);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import { Inject } from '@nestjs/common';
|
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiAccessToken } from '@/models/AccessToken.js';
|
import type { MiAccessToken } from '@/models/AccessToken.js';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
|
@ -12,10 +11,9 @@ import type { NoteReadService } from '@/core/NoteReadService.js';
|
||||||
import type { NotificationService } from '@/core/NotificationService.js';
|
import type { NotificationService } from '@/core/NotificationService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { CacheService } from '@/core/CacheService.js';
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
import { MiFollowing, MiUserProfile, type UserProfilesRepository } from '@/models/_.js';
|
import { MiFollowing, MiUserProfile } from '@/models/_.js';
|
||||||
import type { StreamEventEmitter, GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { StreamEventEmitter, GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
|
||||||
import type { ChannelsService } from './ChannelsService.js';
|
import type { ChannelsService } from './ChannelsService.js';
|
||||||
import type { EventEmitter } from 'events';
|
import type { EventEmitter } from 'events';
|
||||||
import type Channel from './channel.js';
|
import type Channel from './channel.js';
|
||||||
|
@ -47,8 +45,7 @@ export default class Connection {
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private cacheService: CacheService,
|
private cacheService: CacheService,
|
||||||
private channelFollowingService: ChannelFollowingService,
|
private channelFollowingService: ChannelFollowingService,
|
||||||
@Inject(DI.userProfilesRepository)
|
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
|
||||||
user: MiUser | null | undefined,
|
user: MiUser | null | undefined,
|
||||||
token: MiAccessToken | null | undefined,
|
token: MiAccessToken | null | undefined,
|
||||||
) {
|
) {
|
||||||
|
@ -60,7 +57,7 @@ export default class Connection {
|
||||||
public async fetch() {
|
public async fetch() {
|
||||||
if (this.user == null) return;
|
if (this.user == null) return;
|
||||||
const [userProfile, following, followingChannels, userIdsWhoMeMuting, userIdsWhoBlockingMe, userIdsWhoMeMutingRenotes] = await Promise.all([
|
const [userProfile, following, followingChannels, userIdsWhoMeMuting, userIdsWhoBlockingMe, userIdsWhoMeMutingRenotes] = await Promise.all([
|
||||||
await this.userProfilesRepository.findOneByOrFail({ userId: this.user.id }),
|
this.cacheService.userProfileCache.fetch(this.user.id),
|
||||||
this.cacheService.userFollowingsCache.fetch(this.user.id),
|
this.cacheService.userFollowingsCache.fetch(this.user.id),
|
||||||
this.channelFollowingService.userFollowingChannelsCache.fetch(this.user.id),
|
this.channelFollowingService.userFollowingChannelsCache.fetch(this.user.id),
|
||||||
this.cacheService.userMutingsCache.fetch(this.user.id),
|
this.cacheService.userMutingsCache.fetch(this.user.id),
|
||||||
|
|
Loading…
Reference in a new issue