Skip to content

Commit

Permalink
fix(api): comments not working and modifying cache tool
Browse files Browse the repository at this point in the history
  • Loading branch information
manekenpix committed Feb 18, 2025
1 parent 5d1bf13 commit 2dc5085
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 71 deletions.
29 changes: 16 additions & 13 deletions api/package-lock.json

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

3 changes: 2 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"db:format": "npx --yes prisma format"
},
"dependencies": {
"@keyv/redis": "^4.2.0",
"@nestjs/axios": "^4.0.0",
"@nestjs/cache-manager": "^3.0.0",
"@nestjs/common": "^11.0.1",
Expand All @@ -36,9 +37,9 @@
"argon2": "^0.40.1",
"axios": "^1.6.7",
"cache-manager": "^6.4.0",
"cache-manager-redis-store": "^3.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"keyv": "^5.2.3",
"mailgun.js": "^9.3.0",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
Expand Down
8 changes: 7 additions & 1 deletion api/src/comment/comment.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import { PrismaModule } from '../prisma/prisma.module';
import { NotificationModule } from '../notification/notification.module';
import { CommentDao } from './dao/comment.dao';
import { CommentsService } from './comment.service';
import { CacheModule } from '@nestjs/cache-manager';
import { RedisOptions } from 'src/config/redisCache';

@Module({
imports: [PrismaModule, NotificationModule],
imports: [
PrismaModule,
NotificationModule,
CacheModule.registerAsync(RedisOptions),
],
providers: [CommentsService, CommentDao],
exports: [CommentsService],
})
Expand Down
42 changes: 34 additions & 8 deletions api/src/comment/comment.service.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { CommentDao } from './dao/comment.dao';
import { CommentQueryDto } from './dto';
import { CommentDto, CommentQueryDto } from './dto';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

@Injectable()
export class CommentsService {
constructor(private commentDao: CommentDao) {}
constructor(
@Inject(CACHE_MANAGER) private cacheManager: Cache,
private commentDao: CommentDao,
) {}

getComments(query: CommentQueryDto) {
return this.commentDao.getComments(query);
async get(query: CommentQueryDto): Promise<CommentDto[]> {
if (query.listId && !query.userId && !query.commentId) {
let comments = await this.cacheManager.get<CommentDto[]>(
`${query.listId}-comments`,
);

if (comments) {
return comments;
}

comments = await this.commentDao.getComments(query);
await this.cacheManager.set(`${query.listId}-comments`, comments);

return comments;
}

return await this.commentDao.getComments(query);
}

createComment(comment: string, listId: string, userId: string) {
async create(comment: string, listId: string, userId: string) {
await this.cacheManager.del(`${listId}-comments`);

return this.commentDao.createComment(listId, userId, comment);
}

updateComment(comment: string, commentId: string) {
async update(comment: string, commentId: string, listId: string) {
await this.cacheManager.del(`${listId}-comments`);

return this.commentDao.updateComment(commentId, comment);
}

deleteComment(commentId: string) {
async delete(commentId: string, listId: string) {
await this.cacheManager.del(`${listId}-comments`);

return this.commentDao.deleteComment(commentId);
}
}
14 changes: 12 additions & 2 deletions api/src/comment/dao/comment.dao.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CommentQueryDto } from '../dto';
import { CommentDto, CommentQueryDto } from '../dto';

@Injectable()
export class CommentDao {
constructor(private readonly prisma: PrismaService) {}

async getComments(query: CommentQueryDto) {
return await this.prisma.comment.findMany({
const res = await this.prisma.comment.findMany({
where: {
AND: [
{
Expand All @@ -25,6 +25,16 @@ export class CommentDao {
createdAt: 'desc',
},
});

const r: CommentDto[] = res.map((r) => ({
id: r.id,
userId: r.userId,
text: r.text,
createdAt: r.createdAt,
updatedAt: r.updatedAt,
}));

return r;
}

async createComment(listId: string, userId: string, text: string) {
Expand Down
2 changes: 1 addition & 1 deletion api/src/comment/dto/comment.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class CommentDto {

@Expose()
@IsString()
username: string;
userId: string;

@Expose()
@IsString()
Expand Down
2 changes: 1 addition & 1 deletion api/src/comment/guard/comment-auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class CommentAuthorizationGuard implements CanActivate {
const { commentId } = request.params;

const [comments] = await Promise.all([
this.commentService.getComments({
this.commentService.get({
commentId,
}),
]);
Expand Down
20 changes: 12 additions & 8 deletions api/src/config/redisCache.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import KeyvRedis from '@keyv/redis';
import Keyv from 'keyv';
import { CacheModuleAsyncOptions } from '@nestjs/cache-manager';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { redisStore } from 'cache-manager-redis-store';

export const RedisOptions: CacheModuleAsyncOptions = {
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const store = await redisStore({
useFactory: (configService: ConfigService) => {
const redisHost = configService.get<string>('REDIS_HOST') ?? 'locahost';
const port = parseInt(configService.get<string>('REDIS_PORT') ?? '6379');

const store = new KeyvRedis({
url: `redis://${redisHost}:${port.toString()}`,
password: configService.get<string>('REDIS_AUTH') ?? 'docker',
socket: {
host: configService.get<string>('REDIS_HOST'),
port: parseInt(configService.get<string>('REDIS_PORT') ?? '6379'),
reconnectStrategy: parseInt(
configService.get<string>('REDIS_RETRY_INTERVAL') ?? '10000',
),
tls: false,
keepAlive: 30000,
},
password: configService.get<string>('REDIS_AUTH') ?? 'docker',
ttl: 0,
});

return {
store: () => store,
stores: [new Keyv(store)],
};
},

Expand Down
12 changes: 8 additions & 4 deletions api/src/list/list.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export class ListController {
if (!req.user) throw new UnauthorizedException('user not found');

const { id: userId } = req.user;
const createdComment = await this.commentService.createComment(
const createdComment = await this.commentService.create(
text,
listId,
userId,
Expand Down Expand Up @@ -180,16 +180,20 @@ export class ListController {
@HttpCode(HttpStatus.NO_CONTENT)
updateComment(
@Param('commentId') commentId: string,
@Param('id') listId: string,
@Body() updateCommentDto: string,
) {
return this.commentService.updateComment(updateCommentDto, commentId);
return this.commentService.update(updateCommentDto, commentId, listId);
}

@UseGuards(ListAuthGuard, CommentAuthorizationGuard)
@Delete('/:id/comments/:commentId')
@HttpCode(HttpStatus.NO_CONTENT)
deleteComment(@Param('commentId') commentId: string) {
return this.commentService.deleteComment(commentId);
deleteComment(
@Param('commentId') commentId: string,
@Param('id') listId: string,
) {
return this.commentService.delete(commentId, listId);
}

@UseInterceptors(RemoveListFieldsInterceptor)
Expand Down
35 changes: 3 additions & 32 deletions api/src/list/list.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Cache } from 'cache-manager';
import { ListDao } from './dao/list.dao';
import { UserService } from '../user/user.service';
import { ListItem, UpdateListDto } from './dto';
import { CommentDto } from '../comment/dto';
import { NotificationService } from '../notification/notification.service';
import { NotificationTypes } from '../notification/templates';
import { CommentsService } from '../comment/comment.service';
Expand All @@ -27,43 +26,15 @@ export class ListService {
}

async getList(listId: string) {
let list: ListItem | undefined | null = await this.cacheManager.get(listId);

let comments: CommentDto[] | undefined | null = await this.cacheManager.get(
`${listId}-comments`,
);
let list: ListItem | undefined | null =
await this.cacheManager.get<ListItem>(listId);
const comments = await this.commentService.get({ listId });

if (!list) {
list = await this.listDao.getList(listId);
await this.cacheManager.set(listId, list);
}

if (!comments) {
const c = await this.commentService.getComments({ listId });

const commentsWithUsername: CommentDto[] = [];

if (c.length) {
const users = await Promise.all(
c.map((comment) =>
this.userService.getUsers({
id: comment.userId,
} as QueryDto),
),
);

c.forEach((comment, i) =>
commentsWithUsername.push({
...comment,
username: users[i].users[0].username,
}),
);
}
comments = commentsWithUsername;

await this.cacheManager.set(`${listId}-comments`, comments);
}

return {
id: list.id,
name: list.name,
Expand Down

0 comments on commit 2dc5085

Please sign in to comment.