Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Inject, MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { MongooseModule } from '@nestjs/mongoose/dist/mongoose.module';
import { Cache } from 'cache-manager';
import { redisClusterInsStore, redisInsStore } from 'cache-manager-redis-yet';

import * as config from 'src/constants';
Expand Down Expand Up @@ -70,7 +71,7 @@ import { UserModule } from './user';
],
})
export class AppModule implements NestModule {
constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: any) {}
constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}

configure(consumer: MiddlewareConsumer): void {
consumer.apply(RouteLoggerMiddleware).exclude('/hello').forRoutes('*');
Expand Down
8 changes: 8 additions & 0 deletions src/common/cache.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import {
NestInterceptor,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import Debug from 'debug';
import { isArray } from 'lodash';
import { Observable, tap } from 'rxjs';

const debug = Debug('commom:cache-interceptor');

function compileKey(keyStr: string, data: any) {
if (!keyStr) return keyStr;
if (!data) return keyStr;
Expand Down Expand Up @@ -56,9 +59,12 @@ export class UnsetCacheInterceptor implements NestInterceptor {
tap((data) => {
// 从返回结果构造 key
cacheKey = compileKey(cacheKey, data?.toJSON ? data.toJSON() : data);

// 清除缓存
typeof cacheKey === 'string' && // cacheKey 可能用逗号分隔 多个 key
cacheKey.split(',').forEach((key) => this.cacheService.del(key));

debug(`unset cache: ${cacheKey}`);
})
);
}
Expand Down Expand Up @@ -100,6 +106,8 @@ export class SetCacheInterceptor extends CacheInterceptor {
cacheKey = compileKey(cacheKey, { payload, ...payload });
}

debug(`set cache: ${cacheKey}`);

return cacheKey || super.trackBy(context);
}
}
9 changes: 9 additions & 0 deletions src/namespace/namespace.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { CacheKey } from '@nestjs/cache-manager';
import {
Body,
CacheTTL,
ConflictException,
Controller,
Delete,
Expand All @@ -12,6 +14,7 @@ import {
Post,
Query,
Res,
UseInterceptors,
} from '@nestjs/common';
import {
ApiCreatedResponse,
Expand All @@ -24,6 +27,7 @@ import {
} from '@nestjs/swagger';
import { Response } from 'express';

import { SetCacheInterceptor, UnsetCacheInterceptor } from 'src/common';
import { ErrorCodes } from 'src/constants';

import { CreateNamespaceDto } from './dto/create-namespace.dto';
Expand Down Expand Up @@ -117,6 +121,8 @@ export class NamespaceController {
type: 'string',
description: 'Namespace id or key, if key should encodeURIComponent',
})
@UseInterceptors(SetCacheInterceptor)
@CacheTTL(24 * 3600)
@Get(':namespaceIdOrKey')
async get(@Param('namespaceIdOrKey') namespaceIdOrKey: string): Promise<NamespaceDocument> {
const namespace = await this.namespaceService.get(namespaceIdOrKey);
Expand All @@ -137,6 +143,8 @@ export class NamespaceController {
description: 'The namespace updated.',
type: Namespace,
})
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/namespaces/:id,/namespaces/:key')
@Patch(':namespaceIdOrKey')
async update(
@Param('namespaceIdOrKey') namespaceIdOrKey: string,
Expand All @@ -158,6 +166,7 @@ export class NamespaceController {
@ApiOperation({ operationId: 'deleteNamespace' })
@ApiNoContentResponse({ description: 'No content.' })
@HttpCode(HttpStatus.NO_CONTENT)
@UseInterceptors(UnsetCacheInterceptor)
@Delete(':namespaceId')
async delete(@Param('namespaceId') namespaceId: string): Promise<void> {
await this.namespaceService.delete(namespaceId);
Expand Down
25 changes: 24 additions & 1 deletion src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { CacheKey } from '@nestjs/cache-manager';
import {
BadRequestException,
Body,
CacheTTL,
ConflictException,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Inject,
NotFoundException,
Param,
Patch,
Post,
Query,
Res,
UseInterceptors,
} from '@nestjs/common';
import {
ApiCreatedResponse,
Expand All @@ -23,7 +27,9 @@ import {
ApiTags,
} from '@nestjs/swagger';
import { Response } from 'express';
import { RedisClientType } from 'redis';

import { SetCacheInterceptor, UnsetCacheInterceptor } from 'src/common';
import * as config from 'src/constants';
import { NamespaceService } from 'src/namespace';

Expand All @@ -41,7 +47,8 @@ import { verifyIdentity } from './verify-identity';
export class UserController {
constructor(
private readonly userService: UserService,
private readonly namespaceService: NamespaceService
private readonly namespaceService: NamespaceService,
@Inject('REDIS_CLIENT') private readonly redis: RedisClientType
) {}

/**
Expand Down Expand Up @@ -153,6 +160,7 @@ export class UserController {
const count = await this.userService.count(query);
const data = await this.userService.list(query);
res.set({ 'X-Total-Count': count.toString() }).json(data);

return data;
}

Expand All @@ -169,6 +177,8 @@ export class UserController {
type: 'string',
description: 'User id',
})
@UseInterceptors(SetCacheInterceptor)
@CacheTTL(24 * 3600)
@Get(':userId')
async get(@Param('userId') userId: string): Promise<UserDocument> {
const user = await this.userService.get(userId);
Expand All @@ -190,6 +200,8 @@ export class UserController {
type: User,
})
@Patch(':userId')
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
async update(
@Param('userId') userId: string,
@Body() updateDto: UpdateUserDto
Expand Down Expand Up @@ -288,6 +300,8 @@ export class UserController {
description: 'The user upserted.',
type: User,
})
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
@Post(':employeeId/@upsertUserByEmployeeId')
async upsertByEmployeeId(
@Param('employeeId') employeeId: string,
Expand Down Expand Up @@ -387,6 +401,8 @@ export class UserController {
description: 'The user upserted.',
type: User,
})
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
@Post(':username/@upsertUserByUsername')
async upsertByUsername(
@Param('username') username: string,
Expand All @@ -404,6 +420,8 @@ export class UserController {
description: 'The user upserted.',
type: User,
})
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
@Post(':email/@upsertUserByEmail')
async upsertByEmail(
@Param('email') email: string,
Expand All @@ -420,6 +438,8 @@ export class UserController {
description: 'The user upserted.',
type: User,
})
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
@Post(':phone/@upsertUserByPhone')
async upsertByPhone(
@Param('phone') phone: string,
Expand All @@ -434,6 +454,7 @@ export class UserController {
@ApiOperation({ operationId: 'deleteUser' })
@ApiNoContentResponse({ description: 'No content.' })
@HttpCode(HttpStatus.NO_CONTENT)
@UseInterceptors(UnsetCacheInterceptor)
@Delete(':userId')
async delete(@Param('userId') userId: string): Promise<void> {
await this.userService.delete(userId);
Expand All @@ -448,6 +469,8 @@ export class UserController {
type: User,
})
@HttpCode(HttpStatus.OK)
@UseInterceptors(UnsetCacheInterceptor)
@CacheKey('/users/:id')
@Post(':userId/@verifyIdentity')
async verifyIdentity(@Param('userId') userId: string): Promise<UserDocument> {
const user = await this.userService.get(userId);
Expand Down
Loading