normalize cache constructors and detect duplicate cache names
This commit is contained in:
parent
151550602c
commit
8271dc199e
18 changed files with 95 additions and 61 deletions
|
|
@ -36,7 +36,7 @@ export class AvatarDecorationService implements OnApplicationShutdown {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.cache = cacheManagementService.createMemorySingleCache<MiAvatarDecoration[]>(1000 * 60 * 30); // 30s
|
||||
this.cache = cacheManagementService.createMemorySingleCache<MiAvatarDecoration[]>('avatarDecorations', 1000 * 60 * 30); // 30s
|
||||
|
||||
this.internalEventService.on('avatarDecorationCreated', this.onAvatarEvent);
|
||||
this.internalEventService.on('avatarDecorationUpdated', this.onAvatarEvent);
|
||||
|
|
|
|||
|
|
@ -106,10 +106,10 @@ export class CacheService implements OnApplicationShutdown {
|
|||
) {
|
||||
//this.onMessage = this.onMessage.bind(this);
|
||||
|
||||
this.userByIdCache = this.cacheManagementService.createMemoryKVCache<MiUser>(1000 * 60 * 5); // 5m
|
||||
this.localUserByNativeTokenCache = this.cacheManagementService.createMemoryKVCache<MiLocalUser | null>(1000 * 60 * 5); // 5m
|
||||
this.localUserByIdCache = this.cacheManagementService.createMemoryKVCache<MiLocalUser>(1000 * 60 * 5); // 5m
|
||||
this.uriPersonCache = this.cacheManagementService.createMemoryKVCache<MiUser | null>(1000 * 60 * 5); // 5m
|
||||
this.userByIdCache = this.cacheManagementService.createMemoryKVCache<MiUser>('userById', 1000 * 60 * 5); // 5m
|
||||
this.localUserByNativeTokenCache = this.cacheManagementService.createMemoryKVCache<MiLocalUser | null>('localUserByNativeToken', 1000 * 60 * 5); // 5m
|
||||
this.localUserByIdCache = this.cacheManagementService.createMemoryKVCache<MiLocalUser>('localUserById', 1000 * 60 * 5); // 5m
|
||||
this.uriPersonCache = this.cacheManagementService.createMemoryKVCache<MiUser | null>('uriPerson', 1000 * 60 * 5); // 5m
|
||||
|
||||
this.userProfileCache = this.cacheManagementService.createQuantumKVCache('userProfile', {
|
||||
lifetime: 1000 * 60 * 30, // 30m
|
||||
|
|
@ -345,7 +345,7 @@ export class CacheService implements OnApplicationShutdown {
|
|||
},
|
||||
});
|
||||
|
||||
this.userFollowStatsCache = this.cacheManagementService.createMemoryKVCache<FollowStats>(1000 * 60 * 10); // 10 minutes
|
||||
this.userFollowStatsCache = this.cacheManagementService.createMemoryKVCache<FollowStats>('followStats', 1000 * 60 * 10); // 10 minutes
|
||||
|
||||
this.userFollowingChannelsCache = this.cacheManagementService.createQuantumKVCache<Set<string>>('userFollowingChannels', {
|
||||
lifetime: 1000 * 60 * 30, // 30m
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ export class InstanceStatsService {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.localPostsCache = cacheManagementService.createMemorySingleCache<number>(1000 * 60 * 60); // 1h
|
||||
this.localUsersCache = cacheManagementService.createMemorySingleCache<number>(1000 * 60 * 60); // 1h
|
||||
this.activeMonthCache = cacheManagementService.createMemorySingleCache<number>(1000 * 60 * 60 * 24); // 1d
|
||||
this.activeSixMonthsCache = cacheManagementService.createMemorySingleCache<number>(1000 * 60 * 60 * 24 * 7); // 1w
|
||||
this.localPostsCache = cacheManagementService.createMemorySingleCache<number>('localPosts', 1000 * 60 * 60); // 1h
|
||||
this.localUsersCache = cacheManagementService.createMemorySingleCache<number>('localUsers', 1000 * 60 * 60); // 1h
|
||||
this.activeMonthCache = cacheManagementService.createMemorySingleCache<number>('activeMonth', 1000 * 60 * 60 * 24); // 1d
|
||||
this.activeSixMonthsCache = cacheManagementService.createMemorySingleCache<number>('activeSixMonths', 1000 * 60 * 60 * 24 * 7); // 1w
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export class RelayService {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.relaysCache = cacheManagementService.createMemorySingleCache<MiRelay[]>(1000 * 60 * 10); // 10m
|
||||
this.relaysCache = cacheManagementService.createMemorySingleCache<MiRelay[]>('relay', 1000 * 60 * 10); // 10m
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.rolesCache = cacheManagementService.createMemorySingleCache<MiRole[]>(1000 * 60 * 60); // 1h
|
||||
this.roleAssignmentByUserIdCache = cacheManagementService.createMemoryKVCache<MiRoleAssignment[]>(1000 * 60 * 5); // 5m
|
||||
this.rolesCache = cacheManagementService.createMemorySingleCache<MiRole[]>('roles', 1000 * 60 * 60); // 1h
|
||||
this.roleAssignmentByUserIdCache = cacheManagementService.createMemoryKVCache<MiRoleAssignment[]>('roleAssignment', 1000 * 60 * 5); // 5m
|
||||
// TODO additional cache for final calculation?
|
||||
|
||||
this.redisForSub.on('message', this.onMessage);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export class SystemAccountService implements OnApplicationShutdown {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.cache = cacheManagementService.createMemoryKVCache<string>(1000 * 60 * 10); // 10m
|
||||
this.cache = cacheManagementService.createMemoryKVCache<string>('systemAccount', 1000 * 60 * 10); // 10m
|
||||
|
||||
this.redisForSub.on('message', this.onMessage);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export class SystemWebhookService implements OnApplicationShutdown {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.activeSystemWebhooks = cacheManagementService.createMemorySingleCache<MiSystemWebhook[]>(1000 * 60 * 60 * 12); // 12h
|
||||
this.activeSystemWebhooks = cacheManagementService.createMemorySingleCache<MiSystemWebhook[]>('systemWebhooks', 1000 * 60 * 60 * 12); // 12h
|
||||
|
||||
this.internalEventService.on('systemWebhookCreated', this.onWebhookEvent);
|
||||
this.internalEventService.on('systemWebhookUpdated', this.onWebhookEvent);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export class UserWebhookService implements OnApplicationShutdown {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.activeWebhooks = cacheManagementService.createMemorySingleCache<MiWebhook[]>(1000 * 60 * 60 * 12); // 12h
|
||||
this.activeWebhooks = cacheManagementService.createMemorySingleCache<MiWebhook[]>('userWebhooks', 1000 * 60 * 60 * 12); // 12h
|
||||
|
||||
this.internalEventService.on('webhookCreated', this.onWebhookEvent);
|
||||
this.internalEventService.on('webhookUpdated', this.onWebhookEvent);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,15 @@ import {
|
|||
RedisSingleCache,
|
||||
type RedisKVCacheOpts,
|
||||
type RedisSingleCacheOpts,
|
||||
type MemoryCacheServices,
|
||||
type RedisCacheServices,
|
||||
type MemoryCacheOpts,
|
||||
} from '@/misc/cache.js';
|
||||
import { QuantumKVCache, type QuantumKVOpts } from '@/misc/QuantumKVCache.js';
|
||||
import {
|
||||
QuantumKVCache,
|
||||
type QuantumKVOpts,
|
||||
type QuantumCacheServices,
|
||||
} from '@/misc/QuantumKVCache.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { TimeService, type TimerHandle } from '@/global/TimeService.js';
|
||||
|
|
@ -32,6 +39,8 @@ export type ManagedQuantumKVCache<T> = Managed<QuantumKVCache<T>>;
|
|||
export type Managed<T> = Omit<T, 'dispose' | 'onApplicationShutdown' | 'gc'>;
|
||||
export type Manager = { dispose(): void, clear(): void, gc(): void };
|
||||
|
||||
type CacheServices = MemoryCacheServices & RedisCacheServices & QuantumCacheServices;
|
||||
|
||||
export const GC_INTERVAL = 1000 * 60 * 3; // 3m
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +49,7 @@ export const GC_INTERVAL = 1000 * 60 * 3; // 3m
|
|||
*/
|
||||
@Injectable()
|
||||
export class CacheManagementService implements OnApplicationShutdown {
|
||||
private readonly managedCaches = new Set<Manager>();
|
||||
private readonly managedCaches = new Map<string, Manager>();
|
||||
private gcTimer?: TimerHandle | null;
|
||||
|
||||
constructor(
|
||||
|
|
@ -51,7 +60,7 @@ export class CacheManagementService implements OnApplicationShutdown {
|
|||
private readonly internalEventService: InternalEventService,
|
||||
) {}
|
||||
|
||||
private get cacheServices() {
|
||||
private get cacheServices(): CacheServices {
|
||||
return {
|
||||
internalEventService: this.internalEventService,
|
||||
redisClient: this.redisClient,
|
||||
|
|
@ -60,52 +69,56 @@ export class CacheManagementService implements OnApplicationShutdown {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public createMemoryKVCache<T>(lifetime: number): ManagedMemoryKVCache<T> {
|
||||
const cache = new MemoryKVCache<T>(lifetime, this.cacheServices);
|
||||
return this.manageCache(cache);
|
||||
public createMemoryKVCache<T>(name: string, optsOrLifetime: MemoryCacheOpts | number): ManagedMemoryKVCache<T> {
|
||||
const opts = typeof(optsOrLifetime) === 'number' ? { lifetime: optsOrLifetime } : optsOrLifetime;
|
||||
return this.create(name, () => new MemoryKVCache<T>(name, this.cacheServices, opts));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public createMemorySingleCache<T>(lifetime: number): ManagedMemorySingleCache<T> {
|
||||
const cache = new MemorySingleCache<T>(lifetime, this.cacheServices);
|
||||
return this.manageCache(cache);
|
||||
public createMemorySingleCache<T>(name: string, optsOrLifetime: MemoryCacheOpts | number): ManagedMemorySingleCache<T> {
|
||||
const opts = typeof(optsOrLifetime) === 'number' ? { lifetime: optsOrLifetime } : optsOrLifetime;
|
||||
return this.create(name, () => new MemorySingleCache<T>(name, this.cacheServices, opts));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public createRedisKVCache<T>(name: string, opts: RedisKVCacheOpts<T>): ManagedRedisKVCache<T> {
|
||||
const cache = new RedisKVCache<T>(name, this.cacheServices, opts);
|
||||
return this.manageCache(cache);
|
||||
return this.create(name, () => new RedisKVCache<T>(name, this.cacheServices, opts));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public createRedisSingleCache<T>(name: string, opts: RedisSingleCacheOpts<T>): ManagedRedisSingleCache<T> {
|
||||
const cache = new RedisSingleCache<T>(name, this.cacheServices, opts);
|
||||
return this.manageCache(cache);
|
||||
return this.create(name, () => new RedisSingleCache<T>(name, this.cacheServices, opts));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public createQuantumKVCache<T>(name: string, opts: QuantumKVOpts<T>): ManagedQuantumKVCache<T> {
|
||||
const cache = new QuantumKVCache<T>(name, this.cacheServices, opts);
|
||||
return this.manageCache(cache);
|
||||
return this.create(name, () => new QuantumKVCache<T>(name, this.cacheServices, opts));
|
||||
}
|
||||
|
||||
protected manageCache<T extends Manager>(cache: T): Managed<T> {
|
||||
this.managedCaches.add(cache);
|
||||
private create<T extends Manager>(name: string, factory: () => T): T {
|
||||
if (this.managedCaches.has(name)) {
|
||||
throw new Error(`Duplicate cache name: "${name}"`);
|
||||
}
|
||||
|
||||
const cache = factory();
|
||||
|
||||
this.managedCaches.set(name, cache);
|
||||
this.startGcTimer();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public gc(): void {
|
||||
this.resetGcTimer(() => {
|
||||
callAllOn(this.managedCaches, 'gc');
|
||||
callAllOn(this.managedCaches.values(), 'gc');
|
||||
});
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public clear(): void {
|
||||
this.resetGcTimer(() => {
|
||||
callAllOn(this.managedCaches, 'clear');
|
||||
callAllOn(this.managedCaches.values(), 'clear');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +126,7 @@ export class CacheManagementService implements OnApplicationShutdown {
|
|||
public async dispose(): Promise<void> {
|
||||
this.stopGcTimer();
|
||||
|
||||
const toDispose = new Set(this.managedCaches);
|
||||
const toDispose = Array.from(this.managedCaches.values());
|
||||
this.managedCaches.clear();
|
||||
|
||||
callAllOn(toDispose, 'dispose');
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export class DependencyService {
|
|||
protected readonly dependencyVersionCache: ManagedMemoryKVCache<string | null>;
|
||||
|
||||
constructor(cacheManagementService: CacheManagementService) {
|
||||
this.dependencyVersionCache = cacheManagementService.createMemoryKVCache<string | null>(Infinity);
|
||||
this.dependencyVersionCache = cacheManagementService.createMemoryKVCache<string | null>('dependencyVersion', Infinity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export class QuantumKVCache<T> implements Iterable<readonly [key: string, value:
|
|||
) {
|
||||
// OK: we forward all management calls to the inner cache.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
this.memoryCache = new MemoryKVCache(opts.lifetime, services);
|
||||
this.memoryCache = new MemoryKVCache(name + ':mem', services, { lifetime: opts.lifetime });
|
||||
this.fetcher = opts.fetcher;
|
||||
this.bulkFetcher = opts.bulkFetcher;
|
||||
this.onChanged = opts.onChanged;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export class RedisKVCache<T> {
|
|||
this.lifetime = opts.lifetime;
|
||||
// OK: we forward all management calls to the inner cache.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
this.memoryCache = new MemoryKVCache(opts.memoryCacheLifetime, services);
|
||||
this.memoryCache = new MemoryKVCache(name + ':mem', services, { lifetime: opts.memoryCacheLifetime });
|
||||
this.fetcher = opts.fetcher ?? (() => { throw new Error('fetch not supported - use get/set directly'); });
|
||||
this.toRedisConverter = opts.toRedisConverter ?? ((value) => JSON.stringify(value));
|
||||
this.fromRedisConverter = opts.fromRedisConverter ?? ((value) => JSON.parse(value));
|
||||
|
|
@ -151,7 +151,7 @@ export class RedisSingleCache<T> {
|
|||
this.lifetime = opts.lifetime;
|
||||
// OK: we forward all management calls to the inner cache.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
this.memoryCache = new MemorySingleCache(opts.memoryCacheLifetime, services);
|
||||
this.memoryCache = new MemorySingleCache(name + ':mem', services, { lifetime: opts.memoryCacheLifetime });
|
||||
|
||||
this.fetcher = opts.fetcher ?? (() => { throw new Error('fetch not supported - use get/set directly'); });
|
||||
this.toRedisConverter = opts.toRedisConverter ?? ((value) => JSON.stringify(value));
|
||||
|
|
@ -247,17 +247,24 @@ export interface MemoryCacheServices {
|
|||
readonly timeService: TimeService;
|
||||
}
|
||||
|
||||
export interface MemoryCacheOpts {
|
||||
lifetime: number;
|
||||
}
|
||||
|
||||
// TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする?
|
||||
|
||||
export class MemoryKVCache<T> {
|
||||
private readonly cache = new Map<string, { date: number; value: T; }>();
|
||||
private readonly timeService: TimeService;
|
||||
private readonly lifetime: number;
|
||||
|
||||
constructor(
|
||||
private readonly lifetime: number,
|
||||
public readonly name: string,
|
||||
services: MemoryCacheServices,
|
||||
opts: MemoryCacheOpts,
|
||||
) {
|
||||
this.timeService = services.timeService;
|
||||
this.lifetime = opts.lifetime;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
@ -388,14 +395,18 @@ export class MemoryKVCache<T> {
|
|||
|
||||
export class MemorySingleCache<T> {
|
||||
private readonly timeService: TimeService;
|
||||
private readonly lifetime: number;
|
||||
|
||||
private cachedAt: number | null = null;
|
||||
private value: T | undefined;
|
||||
|
||||
constructor(
|
||||
private lifetime: number,
|
||||
public readonly name: string,
|
||||
services: MemoryCacheServices,
|
||||
opts: MemoryCacheOpts,
|
||||
) {
|
||||
this.timeService = services.timeService;
|
||||
this.lifetime = opts.lifetime;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ export class SkRateLimiterService {
|
|||
envService: EnvService,
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.factorCache = cacheManagementService.createMemoryKVCache<number>(1000 * 60); // 1m
|
||||
this.lockoutCache = cacheManagementService.createMemoryKVCache<number>(1000 * 10); // 10s
|
||||
this.factorCache = cacheManagementService.createMemoryKVCache<number>('rateLimitFactor', 1000 * 60); // 1m
|
||||
this.lockoutCache = cacheManagementService.createMemoryKVCache<number>('rateLimitLockout', 1000 * 10); // 10s
|
||||
this.disabled = envService.env.NODE_ENV === 'test';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export class AuthenticateService {
|
|||
|
||||
cacheManagementService: CacheManagementService,
|
||||
) {
|
||||
this.appCache = cacheManagementService.createMemoryKVCache<MiApp>(1000 * 60 * 60 * 24); // 1d
|
||||
this.appCache = cacheManagementService.createMemoryKVCache<MiApp>('app', 1000 * 60 * 60 * 24); // 1d
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
|||
|
|
@ -87,6 +87,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
};
|
||||
});
|
||||
|
||||
this.localEmojiIdsCache = cacheManagementService.createMemorySingleCache<MiEmoji['id'][]>(1000 * 2);
|
||||
this.localEmojiIdsCache = cacheManagementService.createMemorySingleCache<MiEmoji['id'][]>('localEmojis', 1000 * 2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { GodOfTimeService } from './GodOfTimeService.js';
|
|||
import { MockInternalEventService } from './MockInternalEventService.js';
|
||||
import { MockRedis } from './MockRedis.js';
|
||||
import type { QuantumKVOpts } from '@/misc/QuantumKVCache.js';
|
||||
import type { RedisKVCacheOpts, RedisSingleCacheOpts } from '@/misc/cache.js';
|
||||
import type { RedisKVCacheOpts, RedisSingleCacheOpts, MemoryCacheOpts } from '@/misc/cache.js';
|
||||
import type { TimeService } from '@/global/TimeService.js';
|
||||
import type { InternalEventService } from '@/global/InternalEventService.js';
|
||||
import {
|
||||
|
|
@ -40,12 +40,14 @@ export class FakeCacheManagementService extends CacheManagementService {
|
|||
super(redisClient, timeService, internalEventService);
|
||||
}
|
||||
|
||||
createMemoryKVCache<T>(): ManagedMemoryKVCache<T> {
|
||||
return super.createMemoryKVCache(-1);
|
||||
createMemoryKVCache<T>(name: string, optsOrLifetime: number | MemoryCacheOpts): ManagedMemoryKVCache<T> {
|
||||
const opts = typeof(optsOrLifetime) === 'number' ? { lifetime: -1 } : { ...optsOrLifetime, lifetime: -1 };
|
||||
return super.createMemoryKVCache(name, opts);
|
||||
}
|
||||
|
||||
createMemorySingleCache<T>(): ManagedMemorySingleCache<T> {
|
||||
return super.createMemorySingleCache(-1);
|
||||
createMemorySingleCache<T>(name: string, optsOrLifetime: number | MemoryCacheOpts): ManagedMemorySingleCache<T> {
|
||||
const opts = typeof(optsOrLifetime) === 'number' ? { lifetime: -1 } : { ...optsOrLifetime, lifetime: -1 };
|
||||
return super.createMemorySingleCache(name, opts);
|
||||
}
|
||||
|
||||
createRedisKVCache<T>(name: string, opts: RedisKVCacheOpts<T>): ManagedRedisKVCache<T> {
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ describe(CacheManagementService, () => {
|
|||
|
||||
function createCache(): MemoryKVCache<string> {
|
||||
// Cast to allow access to managed functions, for spying purposes.
|
||||
return serviceUnderTest.createMemoryKVCache<string>(Infinity) as MemoryKVCache<string>;
|
||||
return serviceUnderTest.createMemoryKVCache<string>('test', Infinity) as MemoryKVCache<string>;
|
||||
}
|
||||
|
||||
describe('createMemoryKVCache', () => testCreate('createMemoryKVCache', Infinity));
|
||||
describe('createMemorySingleCache', () => testCreate('createMemorySingleCache', Infinity));
|
||||
describe('createRedisKVCache', () => testCreate('createRedisKVCache', 'redis', { lifetime: Infinity, memoryCacheLifetime: Infinity }));
|
||||
describe('createRedisSingleCache', () => testCreate('createRedisSingleCache', 'single', { lifetime: Infinity, memoryCacheLifetime: Infinity }));
|
||||
describe('createQuantumKVCache', () => testCreate('createQuantumKVCache', 'quantum', { lifetime: Infinity, fetcher: () => { throw new Error('not implement'); } }));
|
||||
describe('createMemoryKVCache', () => testCreate('createMemoryKVCache', 'memoryKV', { lifetime: Infinity }));
|
||||
describe('createMemorySingleCache', () => testCreate('createMemorySingleCache', 'memorySingle', { lifetime: Infinity }));
|
||||
describe('createRedisKVCache', () => testCreate('createRedisKVCache', 'redisKV', { lifetime: Infinity, memoryCacheLifetime: Infinity }));
|
||||
describe('createRedisSingleCache', () => testCreate('createRedisSingleCache', 'redisSingle', { lifetime: Infinity, memoryCacheLifetime: Infinity }));
|
||||
describe('createQuantumKVCache', () => testCreate('createQuantumKVCache', 'quantumKV', { lifetime: Infinity, fetcher: () => { throw new Error('not implement'); } }));
|
||||
|
||||
describe('clear', () => {
|
||||
testClear('clear', false);
|
||||
|
|
@ -80,7 +80,7 @@ describe(CacheManagementService, () => {
|
|||
it('should track reference', () => {
|
||||
const cache = act();
|
||||
|
||||
expect(internalsUnderTest.managedCaches).toContain(cache);
|
||||
expect(internalsUnderTest.managedCaches.values()).toContain(cache);
|
||||
});
|
||||
|
||||
it('should start GC timer', () => {
|
||||
|
|
@ -91,6 +91,12 @@ describe(CacheManagementService, () => {
|
|||
|
||||
expect(gc).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('should throw if name is duplicate', () => {
|
||||
act();
|
||||
|
||||
expect(() => act()).toThrow();
|
||||
});
|
||||
}
|
||||
|
||||
function testClear(func: 'clear' | 'dispose' | 'onApplicationShutdown', shouldDispose: boolean) {
|
||||
|
|
@ -140,9 +146,9 @@ describe(CacheManagementService, () => {
|
|||
act();
|
||||
|
||||
if (shouldDispose) {
|
||||
expect(internalsUnderTest.managedCaches).not.toContain(cache);
|
||||
expect(internalsUnderTest.managedCaches.values()).not.toContain(cache);
|
||||
} else {
|
||||
expect(internalsUnderTest.managedCaches).toContain(cache);
|
||||
expect(internalsUnderTest.managedCaches.values()).toContain(cache);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
import { jest } from '@jest/globals';
|
||||
import { GodOfTimeService } from '../../misc/GodOfTimeService.js';
|
||||
import { MockInternalEventService } from '../../misc/MockInternalEventService.js';
|
||||
import { QuantumKVCache, QuantumKVOpts, FetchFailedError, KeyNotFoundError } from '@/misc/QuantumKVCache.js';
|
||||
import { QuantumKVCache, QuantumKVOpts } from '@/misc/QuantumKVCache.js';
|
||||
import { KeyNotFoundError } from '@/misc/errors/KeyNotFoundError.js';
|
||||
import { FetchFailedError } from '@/misc/errors/FetchFailedError.js';
|
||||
|
||||
describe(QuantumKVCache, () => {
|
||||
let fakeTimeService: GodOfTimeService;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue