Skip to content

Commit 9a31380

Browse files
feat(OUT-2940): delete attachments from bucket when a comment is deleted
- [x] directly delete comment attachments from bucket when the comment is deleted - [x] refactor: create separate function that handles attachment deletion
1 parent 036697a commit 9a31380

4 files changed

Lines changed: 44 additions & 28 deletions

File tree

src/app/api/attachments/attachments.service.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import APIError from '@api/core/exceptions/api'
99
import httpStatus from 'http-status'
1010
import { SupabaseService } from '@api/core/services/supabase.service'
1111
import { signedUrlTtl } from '@/constants/attachments'
12+
import { PrismaClient } from '@prisma/client'
1213

1314
export class AttachmentsService extends BaseService {
1415
async getAttachments(taskId: string) {
@@ -91,13 +92,25 @@ export class AttachmentsService extends BaseService {
9192
const policyGate = new PoliciesService(this.user)
9293
policyGate.authorize(UserAction.Delete, Resource.Attachments)
9394

94-
const commentAttachment = await this.db.attachment.findMany({
95-
where: { commentId: commentId, workspaceId: this.user.workspaceId },
96-
})
97-
await this.db.attachment.deleteMany({
98-
where: { commentId: commentId, workspaceId: this.user.workspaceId },
95+
const commentAttachment = await this.db.$transaction(async (tx) => {
96+
this.setTransaction(tx as PrismaClient)
97+
98+
const commentAttachment = await this.db.attachment.findMany({
99+
where: { commentId: commentId, workspaceId: this.user.workspaceId },
100+
})
101+
102+
await this.db.attachment.deleteMany({
103+
where: { commentId: commentId, workspaceId: this.user.workspaceId },
104+
})
105+
106+
this.unsetTransaction()
107+
return commentAttachment
99108
})
100109

101-
return commentAttachment
110+
// directly delete attachments from bucket when deleting comments.
111+
// Postgres transaction is not valid for supabase object so placing it after record deletion from db
112+
const filePathArray = commentAttachment.map((el) => el.filePath)
113+
const supabase = new SupabaseService()
114+
await supabase.removeAttachmentsFromBucket(filePathArray)
102115
}
103116
}

src/app/api/comment/comment.service.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,12 @@ export class CommentService extends BaseService {
107107
const commentExists = await this.db.comment.findFirst({ where: { id } })
108108
if (!commentExists) throw new APIError(httpStatus.NOT_FOUND, 'The comment to delete was not found')
109109

110-
// transaction that deletes the comment and its attachments
111-
const { comment, attachments } = await this.db.$transaction(async (tx) => {
112-
this.setTransaction(tx as PrismaClient)
113-
const comment = await this.db.comment.delete({ where: { id } })
114-
115-
// delete the related attachments as well
116-
const attachmentService = new AttachmentsService(this.user)
117-
attachmentService.setTransaction(tx as PrismaClient)
118-
119-
const attachments = await attachmentService.deleteAttachmentsOfComment(comment.id)
120-
attachmentService.unsetTransaction()
110+
// delete the comment
111+
const comment = await this.db.comment.delete({ where: { id } })
121112

122-
this.unsetTransaction()
123-
return { comment, attachments }
124-
})
113+
// delete the related attachments as well
114+
const attachmentService = new AttachmentsService(this.user)
115+
await attachmentService.deleteAttachmentsOfComment(comment.id)
125116

126117
// transaction that deletes the activity logs
127118
return await this.db.$transaction(async (tx) => {
@@ -150,7 +141,7 @@ export class CommentService extends BaseService {
150141
tasksService.unsetTransaction()
151142

152143
this.unsetTransaction()
153-
return { ...comment, attachments }
144+
return { ...comment, attachments: [] } // send empty attachments array
154145
})
155146
}
156147

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1+
import APIError from '@/app/api/core/exceptions/api'
2+
import { supabaseBucket } from '@/config'
13
import SupabaseClient from '@/lib/supabase'
24
import { type SupabaseClient as SupabaseJSClient } from '@supabase/supabase-js'
5+
import httpStatus from 'http-status'
36

47
/**
58
* Base Service with access to supabase client
69
*/
710
export class SupabaseService {
811
public supabase: SupabaseJSClient = SupabaseClient.getInstance()
12+
13+
async removeAttachmentsFromBucket(attachmentsToDelete: string[]) {
14+
if (attachmentsToDelete.length !== 0) {
15+
const { error } = await this.supabase.storage.from(supabaseBucket).remove(attachmentsToDelete)
16+
if (error) {
17+
console.error(error)
18+
throw new APIError(httpStatus.NOT_FOUND, 'unable to delete some date from supabase')
19+
}
20+
}
21+
}
922
}

src/app/api/workers/scrap-medias/scrap-medias.service.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,13 @@ export class ScrapMediaService {
7777
console.error('Error processing scrap image', e)
7878
}
7979
}
80-
if (scrapMediasToDeleteFromBucket.length !== 0) {
81-
const { error } = await supabase.supabase.storage.from(supabaseBucket).remove(scrapMediasToDeleteFromBucket)
82-
if (error) {
83-
console.error(error)
84-
throw new APIError(404, 'unable to delete some date from supabase')
85-
}
80+
81+
if (!!scrapMediasToDeleteFromBucket.length)
8682
await db.attachment.deleteMany({ where: { filePath: { in: scrapMediasToDeleteFromBucket } } })
87-
}
83+
84+
// remove attachments from bucket
85+
await supabase.removeAttachmentsFromBucket(scrapMediasToDeleteFromBucket)
86+
8887
if (scrapMediasToDelete.length !== 0) {
8988
const idsToDelete = scrapMediasToDelete.map((id) => `'${id}'`).join(', ')
9089
await db.$executeRawUnsafe(`

0 commit comments

Comments
 (0)