mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-03 23:14:13 +00:00 
			
		
		
		
	refactor(backend): misc/cacheをシンプルな実装に戻した
This commit is contained in:
		
							parent
							
								
									cfa573a3a1
								
							
						
					
					
						commit
						f55e1ee138
					
				
					 2 changed files with 17 additions and 65 deletions
				
			
		| 
						 | 
				
			
			@ -16,10 +16,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
 | 
			
		|||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class CacheService implements OnApplicationShutdown {
 | 
			
		||||
	public userByIdCache: MemoryKVCache<MiUser, MiUser | string>;
 | 
			
		||||
	public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null, string | null>;
 | 
			
		||||
	public userByIdCache: MemoryKVCache<MiUser>;
 | 
			
		||||
	public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null>;
 | 
			
		||||
	public localUserByIdCache: MemoryKVCache<MiLocalUser>;
 | 
			
		||||
	public uriPersonCache: MemoryKVCache<MiUser | null, string | null>;
 | 
			
		||||
	public uriPersonCache: MemoryKVCache<MiUser | null>;
 | 
			
		||||
	public userProfileCache: RedisKVCache<MiUserProfile>;
 | 
			
		||||
	public userMutingsCache: RedisKVCache<Set<string>>;
 | 
			
		||||
	public userBlockingCache: RedisKVCache<Set<string>>;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,42 +56,10 @@ export class CacheService implements OnApplicationShutdown {
 | 
			
		|||
	) {
 | 
			
		||||
		//this.onMessage = this.onMessage.bind(this);
 | 
			
		||||
 | 
			
		||||
		const localUserByIdCache = new MemoryKVCache<MiLocalUser>(1000 * 60 * 60 * 6 /* 6h */);
 | 
			
		||||
		this.localUserByIdCache	= localUserByIdCache;
 | 
			
		||||
 | 
			
		||||
		// ローカルユーザーならlocalUserByIdCacheにデータを追加し、こちらにはid(文字列)だけを追加する
 | 
			
		||||
		const userByIdCache = new MemoryKVCache<MiUser, MiUser | string>(1000 * 60 * 60 * 6 /* 6h */, {
 | 
			
		||||
			toMapConverter: user => {
 | 
			
		||||
				if (user.host === null) {
 | 
			
		||||
					localUserByIdCache.set(user.id, user as MiLocalUser);
 | 
			
		||||
					return user.id;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return user;
 | 
			
		||||
			},
 | 
			
		||||
			fromMapConverter: userOrId => typeof userOrId === 'string' ? localUserByIdCache.get(userOrId) : userOrId,
 | 
			
		||||
		});
 | 
			
		||||
		this.userByIdCache = userByIdCache;
 | 
			
		||||
 | 
			
		||||
		this.localUserByNativeTokenCache = new MemoryKVCache<MiLocalUser | null, string | null>(Infinity, {
 | 
			
		||||
			toMapConverter: user => {
 | 
			
		||||
				if (user === null) return null;
 | 
			
		||||
 | 
			
		||||
				localUserByIdCache.set(user.id, user);
 | 
			
		||||
				return user.id;
 | 
			
		||||
			},
 | 
			
		||||
			fromMapConverter: id => id === null ? null : localUserByIdCache.get(id),
 | 
			
		||||
		});
 | 
			
		||||
		this.uriPersonCache = new MemoryKVCache<MiUser | null, string | null>(Infinity, {
 | 
			
		||||
			toMapConverter: user => {
 | 
			
		||||
				if (user === null) return null;
 | 
			
		||||
				if (user.isDeleted) return null;
 | 
			
		||||
 | 
			
		||||
				userByIdCache.set(user.id, user);
 | 
			
		||||
				return user.id;
 | 
			
		||||
			},
 | 
			
		||||
			fromMapConverter: id => id === null ? null : userByIdCache.get(id),
 | 
			
		||||
		});
 | 
			
		||||
		this.userByIdCache = new MemoryKVCache<MiUser>(Infinity);
 | 
			
		||||
		this.localUserByNativeTokenCache = new MemoryKVCache<MiLocalUser | null>(Infinity);
 | 
			
		||||
		this.localUserByIdCache = new MemoryKVCache<MiLocalUser>(Infinity);
 | 
			
		||||
		this.uriPersonCache = new MemoryKVCache<MiUser | null>(Infinity);
 | 
			
		||||
 | 
			
		||||
		this.userProfileCache = new RedisKVCache<MiUserProfile>(this.redisClient, 'userProfile', {
 | 
			
		||||
			lifetime: 1000 * 60 * 30, // 30m
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -186,28 +186,14 @@ export class RedisSingleCache<T> {
 | 
			
		|||
 | 
			
		||||
// TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする?
 | 
			
		||||
 | 
			
		||||
function nothingToDo<T, V = T>(value: T): V {
 | 
			
		||||
	return value as unknown as V;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class MemoryKVCache<T, V = T> {
 | 
			
		||||
	public cache: Map<string, { date: number; value: V; }>;
 | 
			
		||||
export class MemoryKVCache<T> {
 | 
			
		||||
	public cache: Map<string, { date: number; value: T; }>;
 | 
			
		||||
	private lifetime: number;
 | 
			
		||||
	private gcIntervalHandle: NodeJS.Timeout;
 | 
			
		||||
	private toMapConverter: (value: T) => V;
 | 
			
		||||
	private fromMapConverter: (cached: V) => T | undefined;
 | 
			
		||||
	private gcIntervalHandle: NodeJS.Timer;
 | 
			
		||||
 | 
			
		||||
	constructor(lifetime: MemoryKVCache<never>['lifetime'], options: {
 | 
			
		||||
		toMapConverter: (value: T) => V;
 | 
			
		||||
		fromMapConverter: (cached: V) => T | undefined;
 | 
			
		||||
	} = {
 | 
			
		||||
		toMapConverter: nothingToDo,
 | 
			
		||||
		fromMapConverter: nothingToDo,
 | 
			
		||||
	}) {
 | 
			
		||||
	constructor(lifetime: MemoryKVCache<never>['lifetime']) {
 | 
			
		||||
		this.cache = new Map();
 | 
			
		||||
		this.lifetime = lifetime;
 | 
			
		||||
		this.toMapConverter = options.toMapConverter;
 | 
			
		||||
		this.fromMapConverter = options.fromMapConverter;
 | 
			
		||||
 | 
			
		||||
		this.gcIntervalHandle = setInterval(() => {
 | 
			
		||||
			this.gc();
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +204,7 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
	public set(key: string, value: T): void {
 | 
			
		||||
		this.cache.set(key, {
 | 
			
		||||
			date: Date.now(),
 | 
			
		||||
			value: this.toMapConverter(value),
 | 
			
		||||
			value,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +216,7 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
			this.cache.delete(key);
 | 
			
		||||
			return undefined;
 | 
			
		||||
		}
 | 
			
		||||
		return this.fromMapConverter(cached.value);
 | 
			
		||||
		return cached.value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
| 
						 | 
				
			
			@ -241,10 +227,9 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
	/**
 | 
			
		||||
	 * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
 | 
			
		||||
	 * optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
 | 
			
		||||
	 * fetcherの引数はcacheに保存されている値があれば渡されます
 | 
			
		||||
	 */
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public async fetch(key: string, fetcher: (value: V | undefined) => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> {
 | 
			
		||||
	public async fetch(key: string, fetcher: () => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> {
 | 
			
		||||
		const cachedValue = this.get(key);
 | 
			
		||||
		if (cachedValue !== undefined) {
 | 
			
		||||
			if (validator) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +244,7 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// Cache MISS
 | 
			
		||||
		const value = await fetcher(this.cache.get(key)?.value);
 | 
			
		||||
		const value = await fetcher();
 | 
			
		||||
		this.set(key, value);
 | 
			
		||||
		return value;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -267,10 +252,9 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
	/**
 | 
			
		||||
	 * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
 | 
			
		||||
	 * optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
 | 
			
		||||
	 * fetcherの引数はcacheに保存されている値があれば渡されます
 | 
			
		||||
	 */
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public async fetchMaybe(key: string, fetcher: (value: V | undefined) => Promise<T | undefined>, validator?: (cachedValue: T) => boolean): Promise<T | undefined> {
 | 
			
		||||
	public async fetchMaybe(key: string, fetcher: () => Promise<T | undefined>, validator?: (cachedValue: T) => boolean): Promise<T | undefined> {
 | 
			
		||||
		const cachedValue = this.get(key);
 | 
			
		||||
		if (cachedValue !== undefined) {
 | 
			
		||||
			if (validator) {
 | 
			
		||||
| 
						 | 
				
			
			@ -285,7 +269,7 @@ export class MemoryKVCache<T, V = T> {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// Cache MISS
 | 
			
		||||
		const value = await fetcher(this.cache.get(key)?.value);
 | 
			
		||||
		const value = await fetcher();
 | 
			
		||||
		if (value !== undefined) {
 | 
			
		||||
			this.set(key, value);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue