|
|
@@ -10,14 +10,24 @@ import {
|
|
|
RedisInspectorKeySummary,
|
|
|
RedisInspectorRecordDetail,
|
|
|
RedisInspectorRebuildResult,
|
|
|
+ RedisInspectorRebuildSupportResult,
|
|
|
RedisInspectorScanResult,
|
|
|
+ RedisInspectorKeyRebuildResult,
|
|
|
} from './types/redis-inspector.types';
|
|
|
import {
|
|
|
getRedisCacheRegistry,
|
|
|
+ RedisCacheCode,
|
|
|
+ RedisCacheKeyAllowList,
|
|
|
RedisCacheRebuildHandler,
|
|
|
} from './redis-cache-registry';
|
|
|
import { LatestVideosCacheBuilder } from '@box/core/cache/video/latest/latest-videos-cache.builder';
|
|
|
import { RecommendedVideosCacheBuilder } from '@box/core/cache/video/recommended/recommended-videos-cache.builder';
|
|
|
+import { TagCacheBuilder } from '@box/core/cache/tag/tag-cache.builder';
|
|
|
+import { CategoryCacheBuilder } from '@box/core/cache/category/category-cache.builder';
|
|
|
+import { ChannelCacheBuilder } from '@box/core/cache/channel/channel-cache.builder';
|
|
|
+import { AdPoolBuilder } from '@box/core/ad/ad-pool.builder';
|
|
|
+import { RebuildCacheByKeyDto } from './dto/rebuild-by-key.dto';
|
|
|
+import { RebuildSupportDto } from './dto/rebuild-support.dto';
|
|
|
|
|
|
const GROUP_PATTERNS: Record<RedisInspectorGroupCode, string> = {
|
|
|
[RedisInspectorGroupCode.CHANNEL]: 'box:app:channel*',
|
|
|
@@ -37,10 +47,18 @@ export class RedisInspectorService {
|
|
|
private readonly redisService: RedisService,
|
|
|
latestVideosCacheBuilder: LatestVideosCacheBuilder,
|
|
|
recommendedVideosCacheBuilder: RecommendedVideosCacheBuilder,
|
|
|
+ tagCacheBuilder: TagCacheBuilder,
|
|
|
+ categoryCacheBuilder: CategoryCacheBuilder,
|
|
|
+ channelCacheBuilder: ChannelCacheBuilder,
|
|
|
+ adPoolBuilder: AdPoolBuilder,
|
|
|
) {
|
|
|
this.cacheRegistry = getRedisCacheRegistry({
|
|
|
latestVideosCacheBuilder,
|
|
|
recommendedVideosCacheBuilder,
|
|
|
+ tagCacheBuilder,
|
|
|
+ categoryCacheBuilder,
|
|
|
+ channelCacheBuilder,
|
|
|
+ adPoolBuilder,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -137,6 +155,96 @@ export class RedisInspectorService {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ async rebuildByKey(
|
|
|
+ dto: RebuildCacheByKeyDto,
|
|
|
+ ): Promise<RedisInspectorKeyRebuildResult> {
|
|
|
+ const key = dto.key?.trim() ?? '';
|
|
|
+ const rebuiltAtSec = Math.floor(Date.now() / 1000);
|
|
|
+ if (!key || !key.startsWith('box:app:')) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ status: 'NOT_SUPPORTED',
|
|
|
+ rebuiltAtSec,
|
|
|
+ message: 'Invalid key format',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const entry = RedisCacheKeyAllowList.find(({ matcher }) => matcher(key));
|
|
|
+ if (!entry) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ status: 'NOT_SUPPORTED',
|
|
|
+ rebuiltAtSec,
|
|
|
+ message: 'Key is not mapped to a rebuildable cache',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const handler = this.findHandler(entry.cacheCode);
|
|
|
+ if (!handler) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ cacheCode: entry.cacheCode,
|
|
|
+ status: 'NOT_SUPPORTED',
|
|
|
+ rebuiltAtSec,
|
|
|
+ message: `No rebuild handler registered for ${entry.description.toLowerCase()}`,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await handler.rebuild();
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ cacheCode: entry.cacheCode,
|
|
|
+ status: 'OK',
|
|
|
+ rebuiltAtSec,
|
|
|
+ message: result.message,
|
|
|
+ affected: result.affected,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ async rebuildSupport(
|
|
|
+ dto: RebuildSupportDto,
|
|
|
+ ): Promise<RedisInspectorRebuildSupportResult> {
|
|
|
+ const key = dto.key?.trim() ?? '';
|
|
|
+ if (!key || !key.startsWith('box:app:')) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ supported: false,
|
|
|
+ reason: 'Invalid key format',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const entry = RedisCacheKeyAllowList.find(({ matcher }) => matcher(key));
|
|
|
+ if (!entry) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ supported: false,
|
|
|
+ reason: 'Key not in allow list',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const handler = this.findHandler(entry.cacheCode);
|
|
|
+ if (!handler) {
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ cacheCode: entry.cacheCode,
|
|
|
+ supported: false,
|
|
|
+ reason: 'No rebuild handler registered for this cacheCode',
|
|
|
+ description: entry.description,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ key,
|
|
|
+ cacheCode: entry.cacheCode,
|
|
|
+ supported: true,
|
|
|
+ description: entry.description,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ private findHandler(cacheCode: RedisCacheCode) {
|
|
|
+ return this.cacheRegistry.find((entry) => entry.cacheCode === cacheCode);
|
|
|
+ }
|
|
|
+
|
|
|
private async inspectString(
|
|
|
key: string,
|
|
|
ttlSec: number,
|