@mbc-cqrs-serverless/import
Version:
126 lines • 6.27 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var CommandFinishedHandler_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandFinishedHandler = void 0;
const core_1 = require("@mbc-cqrs-serverless/core");
const common_1 = require("@nestjs/common");
const constant_1 = require("../constant");
const enum_1 = require("../enum");
const helpers_1 = require("../helpers");
const import_service_1 = require("../import.service");
// Constants for magic strings to improve maintainability.
const ACTION_COMMAND_STATUS = 'command-status';
let CommandFinishedHandler = CommandFinishedHandler_1 = class CommandFinishedHandler {
constructor(importService) {
this.importService = importService;
this.logger = new common_1.Logger(CommandFinishedHandler_1.name);
}
/**
* Executes the handler logic when a NotificationEvent is received.
* This method orchestrates the validation, parsing, and processing of command status updates.
* @param {NotificationEvent} event The incoming event.
*/
async execute(event) {
this.logger.debug('Processing command notification event...');
try {
// 1. Parse and validate the event payload.
const payload = this.parseAndValidatePayload(event.body);
if (!payload) {
return;
}
const { source, status, result, error } = payload.content;
// 2. Ensure the notification is for a relevant import job.
if (!this.isImportSource(source)) {
this.logger.debug(`Ignoring notification from non-import source: ${source}`);
return;
}
// 3. Map the command status to a final import status (e.g., COMPLETED, FAILED).
const newStatus = this.mapCommandStatusToImportStatus(status);
if (!newStatus) {
this.logger.debug(`Ignoring intermediate command status '${status}' for source ${source}`);
return;
}
// 4. Parse the source string to get the database key.
const importKey = (0, helpers_1.parseId)(source);
if (!importKey) {
return;
}
// 5. Update the import entity with the new status and result/error data.
this.logger.log(`Updating import job ${source} to status ${newStatus}`);
await this.importService.updateStatus(importKey, newStatus, {
result,
error,
});
const skParts = importKey.sk.split(core_1.KEY_SEPARATOR);
const parentId = skParts.slice(0, -1).join(core_1.KEY_SEPARATOR); // Everything except the last part (the child's own ULID)
if (parentId.startsWith(constant_1.CSV_IMPORT_PK_PREFIX)) {
const parentKey = (0, helpers_1.parseId)(parentId);
const childSucceeded = newStatus === enum_1.ImportStatusEnum.COMPLETED;
// This call will handle incrementing and finalizing the parent job.
await this.importService.incrementParentJobCounters(parentKey, childSucceeded);
}
}
catch (error) {
this.logger.error('Failed to process command notification event', error);
throw error;
}
}
/**
* Parses the JSON event body and validates its basic structure.
* @param {string} body The raw event body string.
* @returns {CommandStatusNotification | null} The parsed payload or null if invalid.
*/
parseAndValidatePayload(body) {
try {
const payload = JSON.parse(body);
if (payload.action !== ACTION_COMMAND_STATUS ||
!payload.content?.source) {
this.logger.debug('Ignoring notification: not a valid command status event for import.');
return null;
}
return payload;
}
catch (error) {
this.logger.error('Failed to parse event body as JSON', body);
return null;
}
}
/**
* Checks if the event source is an import job.
* @param {string} source The source identifier from the event.
* @returns {boolean} True if the source is for an import job.
*/
isImportSource(source = '') {
return source.startsWith(`${constant_1.IMPORT_PK_PREFIX}${core_1.KEY_SEPARATOR}`);
}
/**
* Maps a raw command status string to the corresponding ImportStatusEnum.
* @param {string} commandStatus The status string from the command.
* @returns {ImportStatusEnum | null} The mapped status or null if it's not a final status.
*/
mapCommandStatusToImportStatus(commandStatus) {
switch (commandStatus) {
case `${core_1.DataSyncCommandSfnName.FINISH}:${core_1.CommandStatus.STATUS_FINISHED}`:
return enum_1.ImportStatusEnum.COMPLETED;
case `${core_1.DataSyncCommandSfnName.FINISH}:${core_1.CommandStatus.STATUS_FAILED}`:
return enum_1.ImportStatusEnum.FAILED;
default:
return null; // Not a final status we need to handle.
}
}
};
exports.CommandFinishedHandler = CommandFinishedHandler;
exports.CommandFinishedHandler = CommandFinishedHandler = CommandFinishedHandler_1 = __decorate([
(0, core_1.EventHandler)(core_1.NotificationEvent),
__metadata("design:paramtypes", [import_service_1.ImportService])
], CommandFinishedHandler);
//# sourceMappingURL=command-finished.queue.event.handler.js.map