From 5c15a5954bd78dde97495988079a5c5abb4a223a Mon Sep 17 00:00:00 2001 From: Etienne <45695613+etiennejouan@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:34:41 +0200 Subject: [PATCH] Workspace Folder Deletion Error - add logs for investigation (#13385) https://twenty-v7.sentry.io/issues/6565008010/events/latest/?environment=prod&project=4507072499810304&referrer=latest-event&sort=date related to https://github.com/twentyhq/twenty/issues/12299 --- .../file-storage/drivers/s3.driver.ts | 23 +++++++++++++++++++ .../file-workspace-folder-deletion.job.ts | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts index fb9d56b9e..eec6f1e3f 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts @@ -1,3 +1,5 @@ +import { Logger } from '@nestjs/common'; + import fs from 'fs'; import { mkdir } from 'fs/promises'; import { join } from 'path'; @@ -35,6 +37,7 @@ export interface S3DriverOptions extends S3ClientConfig { export class S3Driver implements StorageDriver { private s3Client: S3; private bucketName: string; + private readonly logger = new Logger(S3Driver.name); constructor(options: S3DriverOptions) { const { bucketName, region, endpoint, ...s3Options } = options; @@ -69,6 +72,8 @@ export class S3Driver implements StorageDriver { // @ts-expect-error legacy noImplicitAny private async emptyS3Directory(folderPath) { + this.logger.log(`${folderPath} - emptying folder`); + const listParams = { Bucket: this.bucketName, Prefix: folderPath, @@ -77,6 +82,13 @@ export class S3Driver implements StorageDriver { const listObjectsCommand = new ListObjectsV2Command(listParams); const listedObjects = await this.s3Client.send(listObjectsCommand); + this.logger.log( + `${folderPath} - listed objects`, + listedObjects.Contents, + listedObjects.IsTruncated, + listedObjects.Contents?.length, + ); + if (listedObjects.Contents?.length === 0) return; const deleteParams = { @@ -92,7 +104,11 @@ export class S3Driver implements StorageDriver { await this.s3Client.send(deleteObjectCommand); + this.logger.log(`${folderPath} - objects deleted`); + if (listedObjects.IsTruncated) { + this.logger.log(`${folderPath} - folder is truncated`); + await this.emptyS3Directory(folderPath); } } @@ -101,6 +117,10 @@ export class S3Driver implements StorageDriver { folderPath: string; filename?: string; }): Promise { + this.logger.log( + `${params.folderPath} - deleting file ${params.filename} from folder ${params.folderPath}`, + ); + if (params.filename) { const deleteCommand = new DeleteObjectCommand({ Key: `${params.folderPath}/${params.filename}`, @@ -110,6 +130,9 @@ export class S3Driver implements StorageDriver { await this.s3Client.send(deleteCommand); } else { await this.emptyS3Directory(params.folderPath); + + this.logger.log(`${params.folderPath} - folder is empty`); + const deleteEmptyFolderCommand = new DeleteObjectCommand({ Key: `${params.folderPath}`, Bucket: this.bucketName, diff --git a/packages/twenty-server/src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job.ts b/packages/twenty-server/src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job.ts index 64afa1ebd..84956df11 100644 --- a/packages/twenty-server/src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job.ts +++ b/packages/twenty-server/src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job.ts @@ -18,8 +18,9 @@ export class FileWorkspaceFolderDeletionJob { try { await this.fileService.deleteWorkspaceFolder(workspaceId); } catch (error) { + //todo: clean up error message once issue on workspace folder deletion is fixed + in s3 driver file throw new Error( - `[${FileWorkspaceFolderDeletionJob.name}] Cannot delete workspace folder - ${workspaceId}`, + `[${FileWorkspaceFolderDeletionJob.name}] Cannot delete workspace folder - ${workspaceId} - ${error?.message || error}`, ); } }