From ae8573a75d0c3e3fdd8dac85766db3590dcfe2c6 Mon Sep 17 00:00:00 2001 From: viniciusgadea Date: Mon, 30 Mar 2026 22:39:40 -0300 Subject: [PATCH] FEAT: update delete job endpoint summary and remove unused InputsModule from platform-api module --- docsfera.json | 2 +- .../platform-api/platform-api.controller.ts | 91 +++++++------------ .../platform-api/platform-api.module.ts | 3 +- 3 files changed, 37 insertions(+), 59 deletions(-) diff --git a/docsfera.json b/docsfera.json index 137ea2f..150aaf0 100644 --- a/docsfera.json +++ b/docsfera.json @@ -7630,7 +7630,7 @@ "/platform/jobs/{jobId}": { "delete": { "operationId": "PlatformApiController_deleteJob", - "summary": "Delete a job and sync pipeline data", + "summary": "Delete a job and mark its table as deleted in DynamoDB", "parameters": [ { "name": "jobId", diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts index 0d06347..3e9ca42 100644 --- a/src/modules/platform-api/platform-api.controller.ts +++ b/src/modules/platform-api/platform-api.controller.ts @@ -25,7 +25,6 @@ import { ElasticsearchService } from '../../services/elasticsearch'; import { DynamoDBService, ReferenceColumn } from '../../services/dynamodb'; import { CustomersService } from '../customers/customers.service'; import { validateCronAgainstScheduleLimit } from '../../utils/cron-validation'; -import { InputsService } from '../inputs/inputs.service'; type ValidateTablesDTO = { @@ -45,7 +44,6 @@ export class PlatformApiController { private readonly elasticsearchService: ElasticsearchService, private readonly dynamoDBService: DynamoDBService, private readonly customersService: CustomersService, - private readonly inputsService: InputsService, @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger, ) { this.logger = dadosferaLogger.logger; @@ -936,74 +934,55 @@ export class PlatformApiController { } @Delete('jobs/:jobId') - @ApiOperation({ summary: 'Delete a job and sync pipeline data' }) + @ApiOperation({ summary: 'Delete a job and mark its table as deleted in DynamoDB' }) @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE) async deleteJob( @Param('jobId') jobId: string, @User() user: RequestUser, ) { - // Get job details before deletion to extract table_name and connector type const normalizedJobId = this.normalizeJobId(jobId); - let tableName: string | undefined; + const esPipelineId = this.extractPipelineIdFromJobId(jobId); - this.logger.info('[deleteJob] Start', { jobId }); + // Fetch job details and ES pipeline in parallel — both are reads with no mutual dependency + const [jobResult, esPipelineResult] = await Promise.allSettled([ + this.platformApiService.proxy('GET', `/jobs/${normalizedJobId}`, user), + this.elasticsearchService.getPipeline(user.customer_name, esPipelineId), + ]); - try { - const job = await this.platformApiService.proxy( - 'GET', - `/jobs/${normalizedJobId}`, - user, - ); - tableName = job?.source_config?.table_name; - this.logger.info('[deleteJob] Job fetched', { jobId, tableName }); - } catch (err) { - this.logger.warn('[deleteJob] Could not fetch job before deletion', { jobId, error: err.message }); + const tableName: string | undefined = jobResult.status === 'fulfilled' + ? jobResult.value?.source_config?.table_name + : undefined; + + if (jobResult.status === 'rejected') { + this.logger.warn('deleteJob: could not fetch job before deletion', { jobId, error: jobResult.reason?.message }); } - const result = await this.platformApiService.proxy( - 'DELETE', - `/jobs/${normalizedJobId}`, - user, - ); - this.logger.info('[deleteJob] Job deleted from platform-api', { jobId }); + // Main operation + const result = await this.platformApiService.proxy('DELETE', `/jobs/${normalizedJobId}`, user); - // Mark the table as deleted via in-factory (which has the correct DynamoDB credentials). - // config.tables in ES stores the DynamoDB input ID (legacy naming). - if (tableName) { - try { - const esPipelineId = this.extractPipelineIdFromJobId(jobId); - const esPipeline = await this.elasticsearchService.getPipeline( - user.customer_name, - esPipelineId, - ); - // config.tables holds the DynamoDB input ID (see syncJobInputToDynamoDB for context) - const dynamoInputId = esPipeline?.config?.tables; + // Sync deleted status to DynamoDB — follows syncJobInputToDynamoDB pattern + // config.tables in ES stores the DynamoDB input ID (legacy field naming) + const dynamoInputId: string | undefined = esPipelineResult.status === 'fulfilled' + ? esPipelineResult.value?.config?.tables + : undefined; - if (dynamoInputId) { - const info = { customer_id: user.customer_id, user_id: user.user_id, customer: user.customer_name }; + if (esPipelineResult.status === 'rejected') { + this.logger.warn('deleteJob: could not fetch ES pipeline for DynamoDB sync', { jobId, error: esPipelineResult.reason?.message }); + } - // Read current input to get full tables array (adjustInputPayload flattens the response) - const { input } = await this.inputsService.findOne({ id: dynamoInputId, info }); - const currentTables: any[] = input?.tables ?? []; - - const updatedTables = currentTables.map((t: any) => - t.name === tableName ? { ...t, status: 'deleted' } : t, - ); - - await this.inputsService.update(dynamoInputId, { tables: updatedTables }, info); - this.logger.info('[deleteJob] Marked table as deleted via in-factory', { jobId, tableName }); - } else { - this.logger.warn('[deleteJob] No input ID in ES pipeline, skipping DynamoDB update', { jobId, tableName }); - } - } catch (error) { - this.logger.error('[deleteJob] Failed to mark table as deleted via in-factory', { - jobId, - tableName, - error: error.message, - }); - } + if (tableName && dynamoInputId) { + await this.dynamoDBService.updateInputTable( + user.customer_id, + dynamoInputId, + tableName, + { status: 'deleted' }, + ).catch((error) => { + this.logger.error('Failed to sync job deletion to DynamoDB', { jobId, tableName, error: error.message }); + }); + } else if (!tableName) { + this.logger.warn('deleteJob: table name not resolved, skipping DynamoDB sync', { jobId }); } else { - this.logger.warn('[deleteJob] tableName not resolved, skipping DynamoDB update', { jobId }); + this.logger.warn('deleteJob: no input ID in ES pipeline, skipping DynamoDB sync', { jobId }); } return result; diff --git a/src/modules/platform-api/platform-api.module.ts b/src/modules/platform-api/platform-api.module.ts index 3c9ff86..074cc2d 100644 --- a/src/modules/platform-api/platform-api.module.ts +++ b/src/modules/platform-api/platform-api.module.ts @@ -7,11 +7,10 @@ import { PlatformApiService } from './platform-api.service'; import { ElasticsearchModule } from '../../services/elasticsearch'; import { DynamoDBModule } from '../../services/dynamodb'; import { CustomersModule } from '../customers/customers.module'; -import { InputsModule } from '../inputs/inputs.module'; import { PipelinesV2Module } from '../pipelinesV2/pipelines.module'; @Module({ - imports: [ElasticsearchModule, DynamoDBModule, CustomersModule, InputsModule, PipelinesV2Module], + imports: [ElasticsearchModule, DynamoDBModule, CustomersModule, PipelinesV2Module], controllers: [PlatformApiController], providers: [PlatformApiService, DadosferaLogger], exports: [PlatformApiService],