Skip to content

Commit

Permalink
cache implemented with redis
Browse files Browse the repository at this point in the history
  • Loading branch information
AHS12 committed Oct 25, 2024
1 parent f023168 commit 87359dc
Show file tree
Hide file tree
Showing 12 changed files with 439 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1 +1 @@
npm run test
npm run test:cov
80 changes: 80 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.17",
"@types/ioredis-mock": "^8.2.5",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/passport-jwt": "^4.0.1",
Expand All @@ -81,6 +82,7 @@
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"husky": "^9.1.6",
"ioredis-mock": "^8.9.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
Expand Down
4 changes: 2 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import { XSecureInstallCommand } from './commands/xsecurity.command';
import mikroOrmConfig from './config/mikro-orm.config';
import { XSecurityMiddleware } from './middlewares/xsecurity.middleware';
import { AuthModule } from './modules/auth/auth.module';
import { CacheModule } from './modules/cache/cache.module';
import { HealthModule } from './modules/health/health.module';
import { MiscModule } from './modules/misc/misc.module';
import { PermissionModule } from './modules/permission/permission.module';
import { RoleModule } from './modules/role/role.module';
import { UserModule } from './modules/user/user.module';
import { CacheModule } from './modules/cache/cache.module';

@Module({
imports: [
Expand Down Expand Up @@ -43,11 +43,11 @@ import { CacheModule } from './modules/cache/cache.module';
CommandModule,
HealthModule,
MiscModule,
CacheModule,
PermissionModule,
RoleModule,
UserModule,
AuthModule,
CacheModule,
],
controllers: [AppController],
providers: [
Expand Down
77 changes: 77 additions & 0 deletions src/mocks/redis.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Redis from 'ioredis';

export class RedisMock implements Partial<Redis> {
private store = new Map<string, { value: string; expireAt: number | null }>();

get = jest.fn(async (key: string): Promise<string | null> => {
const data = this.store.get(key);
if (!data) return null;

if (data.expireAt !== null && Date.now() > data.expireAt) {
this.store.delete(key);
return null;
}
return data.value;
});

set = jest.fn(async (key: string, value: string): Promise<'OK'> => {
this.store.set(key, { value, expireAt: null });
return 'OK' as const;
});

setex = jest.fn(
async (key: string, ttl: number, value: string): Promise<'OK'> => {
const expireAt = Date.now() + ttl * 1000;
this.store.set(key, { value, expireAt });
return 'OK' as const;
},
);

del = jest.fn(async (...keys: (string | Buffer)[]): Promise<number> => {
let count = 0;
for (const key of keys) {
if (this.store.delete(String(key))) {
count++;
}
}
return count;
}) as unknown as Redis['del'];

exists = jest.fn(async (...keys: string[]): Promise<number> => {
let count = 0;
for (const key of keys) {
const data = this.store.get(key);
if (!data) continue;

if (data.expireAt !== null && Date.now() > data.expireAt) {
this.store.delete(key);
continue;
}

count++;
}
return count;
}) as unknown as Redis['exists'];

keys = jest.fn(async (pattern: string): Promise<string[]> => {
const regex = new RegExp(`^${pattern.replace('*', '.*')}$`);
return Array.from(this.store.keys()).filter((key) => regex.test(key));
});

ttl = jest.fn(async (key: string): Promise<number> => {
const data = this.store.get(key);
if (!data || data.expireAt === null) return -1;

const ttl = Math.max(0, Math.floor((data.expireAt - Date.now()) / 1000));
return ttl > 0 ? ttl : -2;
});

quit = jest.fn(async (): Promise<'OK'> => {
return 'OK' as const;
});

flushall = jest.fn(async (): Promise<'OK'> => {
this.store.clear();
return 'OK' as const;
});
}
2 changes: 0 additions & 2 deletions src/modules/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { MiscModule } from '../misc/misc.module';
import { UserModule } from '../user/user.module';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
Expand All @@ -19,7 +18,6 @@ import { JwtStrategy } from './strategies/jwt.strategy';
}),
inject: [ConfigService],
}),
MiscModule,
UserModule,
],
providers: [ConfigService, AuthService, JwtStrategy],
Expand Down
3 changes: 2 additions & 1 deletion src/modules/cache/cache.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { RedisModule } from '@nestjs-modules/ioredis';
import { Module } from '@nestjs/common';
import { Global, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { CacheService } from './cache.service';

@Global()
@Module({
imports: [
RedisModule.forRootAsync({
Expand Down
Loading

0 comments on commit 87359dc

Please sign in to comment.