From 598809adfd4e2877d6ed75631f2cd77ef74f2e4a Mon Sep 17 00:00:00 2001 From: Sergej Hoffmann <97111299+SevenWaysDP@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:36:24 +0100 Subject: [PATCH] BC-5755 - Column board does not show any preview images (#4554) * BC-5755 - add coreModule for correct error handling --- Dockerfile | 1 + .../preview-generator-configmap.yml.j2 | 1 + .../preview-generator.consumer.ts | 6 +++-- .../preview-generator.service.ts | 6 ++--- .../preview-generator/preview.producer.ts | 7 ++--- .../src/infra/s3-client/s3-client.adapter.ts | 26 +++++++++---------- .../files-preview-amqp.module.ts | 8 ++++-- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8663c9b8d85..77ed4a1088b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,4 +24,5 @@ COPY scripts/ldapSync.sh /schulcloud-server/scripts/ RUN npm run build ENV NODE_ENV=production +ENV NO_COLOR="true" CMD npm run start diff --git a/ansible/roles/schulcloud-server-core/templates/preview-generator-configmap.yml.j2 b/ansible/roles/schulcloud-server-core/templates/preview-generator-configmap.yml.j2 index 457a5e47364..8d3a4b1f4c2 100644 --- a/ansible/roles/schulcloud-server-core/templates/preview-generator-configmap.yml.j2 +++ b/ansible/roles/schulcloud-server-core/templates/preview-generator-configmap.yml.j2 @@ -6,3 +6,4 @@ metadata: labels: app: preview-generator data: + NEST_LOG_LEVEL: "info" diff --git a/apps/server/src/infra/preview-generator/preview-generator.consumer.ts b/apps/server/src/infra/preview-generator/preview-generator.consumer.ts index d34fc8bc37c..7e1a5c523ae 100644 --- a/apps/server/src/infra/preview-generator/preview-generator.consumer.ts +++ b/apps/server/src/infra/preview-generator/preview-generator.consumer.ts @@ -1,7 +1,7 @@ import { RabbitPayload, RabbitRPC } from '@golevelup/nestjs-rabbitmq'; +import { FilesPreviewEvents, FilesPreviewExchange } from '@infra/rabbitmq'; import { Injectable } from '@nestjs/common'; import { Logger } from '@src/core/logger'; -import { FilesPreviewEvents, FilesPreviewExchange } from '@infra/rabbitmq'; import { PreviewFileOptions } from './interface'; import { PreviewActionsLoggable } from './loggable/preview-actions.loggable'; import { PreviewGeneratorService } from './preview-generator.service'; @@ -18,10 +18,12 @@ export class PreviewGeneratorConsumer { queue: FilesPreviewEvents.GENERATE_PREVIEW, }) public async generatePreview(@RabbitPayload() payload: PreviewFileOptions) { - this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview', payload)); + this.logger.info(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview:start', payload)); const response = await this.previewGeneratorService.generatePreview(payload); + this.logger.info(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview:end', payload)); + return { message: response }; } } diff --git a/apps/server/src/infra/preview-generator/preview-generator.service.ts b/apps/server/src/infra/preview-generator/preview-generator.service.ts index 83dca461a2f..35b52d5e174 100644 --- a/apps/server/src/infra/preview-generator/preview-generator.service.ts +++ b/apps/server/src/infra/preview-generator/preview-generator.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from '@nestjs/common'; import { GetFile, S3ClientAdapter } from '@infra/s3-client'; +import { Injectable } from '@nestjs/common'; import { Logger } from '@src/core/logger'; import { subClass } from 'gm'; import { PassThrough } from 'stream'; @@ -16,7 +16,7 @@ export class PreviewGeneratorService { } public async generatePreview(params: PreviewFileOptions): Promise { - this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:start', params)); + this.logger.info(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:start', params)); const { originFilePath, previewFilePath, previewOptions } = params; const original = await this.downloadOriginFile(originFilePath); @@ -26,7 +26,7 @@ export class PreviewGeneratorService { await this.storageClient.create(previewFilePath, file); - this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:end', params)); + this.logger.info(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:end', params)); return { previewFilePath, diff --git a/apps/server/src/infra/preview-generator/preview.producer.ts b/apps/server/src/infra/preview-generator/preview.producer.ts index 28cf6930830..8c84e93b295 100644 --- a/apps/server/src/infra/preview-generator/preview.producer.ts +++ b/apps/server/src/infra/preview-generator/preview.producer.ts @@ -1,7 +1,7 @@ import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; +import { FilesPreviewEvents, FilesPreviewExchange, RpcMessageProducer } from '@infra/rabbitmq'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { FilesPreviewEvents, FilesPreviewExchange, RpcMessageProducer } from '@infra/rabbitmq'; import { Logger } from '@src/core/logger'; import { PreviewFileOptions, PreviewResponseMessage } from './interface'; import { PreviewModuleConfig } from './interface/preview-consumer-config'; @@ -21,10 +21,11 @@ export class PreviewProducer extends RpcMessageProducer { } async generate(payload: PreviewFileOptions): Promise { - this.logger.debug(new PreviewActionsLoggable('PreviewProducer.generate:started', payload)); + this.logger.info(new PreviewActionsLoggable('PreviewProducer.generate:started', payload)); + const response = await this.request(FilesPreviewEvents.GENERATE_PREVIEW, payload); - this.logger.debug(new PreviewActionsLoggable('PreviewProducer.generate:finished', payload)); + this.logger.info(new PreviewActionsLoggable('PreviewProducer.generate:finished', payload)); return response; } diff --git a/apps/server/src/infra/s3-client/s3-client.adapter.ts b/apps/server/src/infra/s3-client/s3-client.adapter.ts index 3c83fce7413..1ed693a4d52 100644 --- a/apps/server/src/infra/s3-client/s3-client.adapter.ts +++ b/apps/server/src/infra/s3-client/s3-client.adapter.ts @@ -33,7 +33,7 @@ export class S3ClientAdapter { // is public but only used internally public async createBucket() { try { - this.logger.log({ action: 'create bucket', params: { bucket: this.config.bucket } }); + this.logger.debug({ action: 'create bucket', params: { bucket: this.config.bucket } }); const req = new CreateBucketCommand({ Bucket: this.config.bucket }); await this.client.send(req); @@ -50,7 +50,7 @@ export class S3ClientAdapter { public async get(path: string, bytesRange?: string): Promise { try { - this.logger.log({ action: 'get', params: { path, bucket: this.config.bucket } }); + this.logger.debug({ action: 'get', params: { path, bucket: this.config.bucket } }); const req = new GetObjectCommand({ Bucket: this.config.bucket, @@ -73,8 +73,8 @@ export class S3ClientAdapter { } catch (err) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (err?.Code === 'NoSuchKey') { - this.logger.log(`could not find one of the files for deletion with id ${path}`); - throw new NotFoundException('NoSuchKey'); + this.logger.warn(`could not find one of the files for deletion with id ${path}`); + throw new NotFoundException('NoSuchKey', ErrorUtils.createHttpExceptionOptions(err)); } else { throw new InternalServerErrorException('S3ClientAdapter:get', ErrorUtils.createHttpExceptionOptions(err)); } @@ -83,7 +83,7 @@ export class S3ClientAdapter { public async create(path: string, file: File): Promise { try { - this.logger.log({ action: 'create', params: { path, bucket: this.config.bucket } }); + this.logger.debug({ action: 'create', params: { path, bucket: this.config.bucket } }); const req = { Body: file.data, @@ -126,7 +126,7 @@ export class S3ClientAdapter { } catch (err) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (err?.cause?.name === 'NoSuchKey') { - this.logger.log(`could not find one of the files for deletion with ids ${paths.join(',')}`); + this.logger.warn(`could not find one of the files for deletion with ids ${paths.join(',')}`); return []; } throw new InternalServerErrorException('S3ClientAdapter:delete', ErrorUtils.createHttpExceptionOptions(err)); @@ -135,7 +135,7 @@ export class S3ClientAdapter { public async restore(paths: string[]): Promise { try { - this.logger.log({ action: 'restore', params: { paths, bucket: this.config.bucket } }); + this.logger.debug({ action: 'restore', params: { paths, bucket: this.config.bucket } }); const copyPaths = paths.map((path) => { return { sourcePath: `${this.deletedFolderName}/${path}`, targetPath: path }; @@ -156,7 +156,7 @@ export class S3ClientAdapter { public async copy(paths: CopyFiles[]) { try { - this.logger.log({ action: 'copy', params: { paths, bucket: this.config.bucket } }); + this.logger.debug({ action: 'copy', params: { paths, bucket: this.config.bucket } }); const copyRequests = paths.map(async (path) => { const req = new CopyObjectCommand({ @@ -180,7 +180,7 @@ export class S3ClientAdapter { public async delete(paths: string[]) { try { - this.logger.log({ action: 'delete', params: { paths, bucket: this.config.bucket } }); + this.logger.debug({ action: 'delete', params: { paths, bucket: this.config.bucket } }); const pathObjects = paths.map((p) => { return { Key: p }; @@ -200,7 +200,7 @@ export class S3ClientAdapter { public async list(params: ListFiles): Promise { try { - this.logger.log({ action: 'list', params }); + this.logger.debug({ action: 'list', params }); const result = await this.listObjectKeysRecursive(params); @@ -242,7 +242,7 @@ export class S3ClientAdapter { public async head(path: string): Promise { try { - this.logger.log({ action: 'head', params: { path, bucket: this.config.bucket } }); + this.logger.debug({ action: 'head', params: { path, bucket: this.config.bucket } }); const req = new HeadObjectCommand({ Bucket: this.config.bucket, @@ -255,7 +255,7 @@ export class S3ClientAdapter { } catch (err) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (err.message && err.message === 'NoSuchKey') { - this.logger.log(`could not find the file for head with id ${path}`); + this.logger.warn(`could not find the file for head with id ${path}`); throw new NotFoundException(null, ErrorUtils.createHttpExceptionOptions(err, 'NoSuchKey')); } throw new InternalServerErrorException(null, ErrorUtils.createHttpExceptionOptions(err, 'S3ClientAdapter:head')); @@ -264,7 +264,7 @@ export class S3ClientAdapter { public async deleteDirectory(path: string) { try { - this.logger.log({ action: 'deleteDirectory', params: { path, bucket: this.config.bucket } }); + this.logger.debug({ action: 'deleteDirectory', params: { path, bucket: this.config.bucket } }); const req = new ListObjectsV2Command({ Bucket: this.config.bucket, diff --git a/apps/server/src/modules/files-storage/files-preview-amqp.module.ts b/apps/server/src/modules/files-storage/files-preview-amqp.module.ts index 78a1aec0129..c59dc720729 100644 --- a/apps/server/src/modules/files-storage/files-preview-amqp.module.ts +++ b/apps/server/src/modules/files-storage/files-preview-amqp.module.ts @@ -1,8 +1,12 @@ -import { Module } from '@nestjs/common'; import { PreviewGeneratorConsumerModule } from '@infra/preview-generator'; +import { Module } from '@nestjs/common'; +import { CoreModule } from '@src/core'; import { defaultConfig, s3Config } from './files-storage.config'; @Module({ - imports: [PreviewGeneratorConsumerModule.register({ storageConfig: s3Config, serverConfig: defaultConfig })], + imports: [ + PreviewGeneratorConsumerModule.register({ storageConfig: s3Config, serverConfig: defaultConfig }), + CoreModule, + ], }) export class PreviewGeneratorAMQPModule {}