@mbc-cqrs-serverless/import 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/constant/id.d.ts +3 -0
  2. package/dist/constant/id.js +7 -0
  3. package/dist/constant/id.js.map +1 -0
  4. package/dist/constant/index.d.ts +2 -1
  5. package/dist/constant/index.js +16 -2
  6. package/dist/constant/index.js.map +1 -1
  7. package/dist/constant/queue.d.ts +2 -0
  8. package/dist/constant/queue.js +6 -0
  9. package/dist/constant/queue.js.map +1 -0
  10. package/dist/dto/create-csv-import.dto.d.ts +1 -0
  11. package/dist/dto/create-csv-import.dto.js +5 -0
  12. package/dist/dto/create-csv-import.dto.js.map +1 -1
  13. package/dist/dto/create-import.dto.d.ts +1 -0
  14. package/dist/dto/create-import.dto.js +5 -0
  15. package/dist/dto/create-import.dto.js.map +1 -1
  16. package/dist/dto/create-zip-import.dto.d.ts +5 -0
  17. package/dist/dto/create-zip-import.dto.js +32 -0
  18. package/dist/dto/create-zip-import.dto.js.map +1 -0
  19. package/dist/dto/index.d.ts +1 -0
  20. package/dist/dto/index.js +1 -0
  21. package/dist/dto/index.js.map +1 -1
  22. package/dist/entity/import-entity.d.ts +4 -0
  23. package/dist/entity/import-entity.js +1 -0
  24. package/dist/entity/import-entity.js.map +1 -1
  25. package/dist/event/command-finished.queue.event.handler.d.ts +31 -0
  26. package/dist/event/command-finished.queue.event.handler.js +126 -0
  27. package/dist/event/command-finished.queue.event.handler.js.map +1 -0
  28. package/dist/event/csv-import.queue.event.handler.js +7 -3
  29. package/dist/event/csv-import.queue.event.handler.js.map +1 -1
  30. package/dist/event/csv-import.sfn.event.handler.d.ts +2 -0
  31. package/dist/event/csv-import.sfn.event.handler.js +57 -3
  32. package/dist/event/csv-import.sfn.event.handler.js.map +1 -1
  33. package/dist/event/import-status.queue.event.d.ts +15 -0
  34. package/dist/event/import-status.queue.event.handler.d.ts +16 -0
  35. package/dist/event/import-status.queue.event.handler.js +82 -0
  36. package/dist/event/import-status.queue.event.handler.js.map +1 -0
  37. package/dist/event/import-status.queue.event.js +13 -0
  38. package/dist/event/import-status.queue.event.js.map +1 -0
  39. package/dist/event/import.queue.event.handler.js +40 -15
  40. package/dist/event/import.queue.event.handler.js.map +1 -1
  41. package/dist/event/index.d.ts +6 -0
  42. package/dist/event/index.js +6 -0
  43. package/dist/event/index.js.map +1 -1
  44. package/dist/event/zip-import.queue.event.handler.d.ts +25 -0
  45. package/dist/event/zip-import.queue.event.handler.js +183 -0
  46. package/dist/event/zip-import.queue.event.handler.js.map +1 -0
  47. package/dist/event/zip-import.sfn.event.d.ts +8 -0
  48. package/dist/event/zip-import.sfn.event.handler.d.ts +21 -0
  49. package/dist/event/zip-import.sfn.event.handler.js +94 -0
  50. package/dist/event/zip-import.sfn.event.handler.js.map +1 -0
  51. package/dist/event/zip-import.sfn.event.js +34 -0
  52. package/dist/event/zip-import.sfn.event.js.map +1 -0
  53. package/dist/helpers/id.d.ts +2 -0
  54. package/dist/helpers/id.js +15 -0
  55. package/dist/helpers/id.js.map +1 -0
  56. package/dist/helpers/index.d.ts +1 -0
  57. package/dist/helpers/index.js +18 -0
  58. package/dist/helpers/index.js.map +1 -0
  59. package/dist/import.controller.d.ts +2 -0
  60. package/dist/import.controller.js +26 -0
  61. package/dist/import.controller.js.map +1 -1
  62. package/dist/import.module.js +8 -0
  63. package/dist/import.module.js.map +1 -1
  64. package/dist/import.service.d.ts +30 -1
  65. package/dist/import.service.js +156 -3
  66. package/dist/import.service.js.map +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +1 -0
  69. package/dist/index.js.map +1 -1
  70. package/package.json +3 -3
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var ImportStatusHandler_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ImportStatusHandler = void 0;
14
+ const client_sfn_1 = require("@aws-sdk/client-sfn");
15
+ const core_1 = require("@mbc-cqrs-serverless/core");
16
+ const common_1 = require("@nestjs/common");
17
+ const constant_1 = require("../constant");
18
+ const import_service_1 = require("../import.service");
19
+ const import_status_queue_event_1 = require("./import-status.queue.event");
20
+ const enum_1 = require("../enum");
21
+ let ImportStatusHandler = ImportStatusHandler_1 = class ImportStatusHandler {
22
+ constructor(importService, sfnService) {
23
+ this.importService = importService;
24
+ this.sfnService = sfnService;
25
+ this.logger = new common_1.Logger(ImportStatusHandler_1.name);
26
+ }
27
+ async execute(event) {
28
+ const notification = JSON.parse(event.body);
29
+ // 1. Filter for the specific event: a completed master CSV job.
30
+ const pk = notification.pk;
31
+ const status = notification.content?.status;
32
+ if (status !== enum_1.ImportStatusEnum.COMPLETED ||
33
+ !pk?.startsWith(`${constant_1.CSV_IMPORT_PK_PREFIX}${core_1.KEY_SEPARATOR}`)) {
34
+ return;
35
+ }
36
+ this.logger.log(`Received completed master CSV job event for: ${notification.id}`);
37
+ try {
38
+ // 2. Get the full import job entity from DynamoDB.
39
+ const importKey = { pk: notification.pk, sk: notification.sk };
40
+ const importJob = await this.importService.getImportByKey(importKey);
41
+ if (!importJob) {
42
+ this.logger.warn(`Could not find import job for key:`, importKey);
43
+ return;
44
+ }
45
+ // 3. Check if a taskToken was saved in its attributes.
46
+ const taskToken = importJob.attributes?.taskToken;
47
+ if (taskToken) {
48
+ this.logger.log(`Found task token. Resuming Step Function.`);
49
+ // 4. Send the success signal back to the waiting Step Function.
50
+ // The output can be the result summary from the import job itself.
51
+ await this.sendTaskSuccess(taskToken, importJob.result);
52
+ }
53
+ else {
54
+ this.logger.log('No task token found in import job attributes. Nothing to do.');
55
+ }
56
+ }
57
+ catch (error) {
58
+ this.logger.error('Error in ImportStatusHandler:', error);
59
+ throw error;
60
+ }
61
+ }
62
+ /**
63
+ * Sends a success signal to a waiting Step Function task.
64
+ * @param taskToken The unique token of the paused task.
65
+ * @param output The JSON output to send back to the state machine.
66
+ */
67
+ async sendTaskSuccess(taskToken, output) {
68
+ this.logger.log(`Sending task success for token: ${taskToken}`);
69
+ return this.sfnService.client.send(new client_sfn_1.SendTaskSuccessCommand({
70
+ taskToken: taskToken,
71
+ output: JSON.stringify(output),
72
+ }));
73
+ }
74
+ };
75
+ exports.ImportStatusHandler = ImportStatusHandler;
76
+ exports.ImportStatusHandler = ImportStatusHandler = ImportStatusHandler_1 = __decorate([
77
+ (0, common_1.Injectable)(),
78
+ (0, core_1.EventHandler)(import_status_queue_event_1.ImportStatusQueueEvent),
79
+ __metadata("design:paramtypes", [import_service_1.ImportService,
80
+ core_1.StepFunctionService])
81
+ ], ImportStatusHandler);
82
+ //# sourceMappingURL=import-status.queue.event.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-status.queue.event.handler.js","sourceRoot":"","sources":["../../src/event/import-status.queue.event.handler.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,oDAA4D;AAC5D,oDAMkC;AAClC,2CAAmD;AAEnD,0CAAkD;AAClD,sDAAiD;AACjD,2EAAoE;AACpE,kCAA0C;AAInC,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAK9B,YACmB,aAA4B,EAC5B,UAA+B;QAD/B,kBAAa,GAAb,aAAa,CAAe;QAC5B,eAAU,GAAV,UAAU,CAAqB;QAJjC,WAAM,GAAG,IAAI,eAAM,CAAC,qBAAmB,CAAC,IAAI,CAAC,CAAA;IAK3D,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,KAA6B;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAE3C,gEAAgE;QAChE,MAAM,EAAE,GAAG,YAAY,CAAC,EAAY,CAAA;QACpC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAA;QAE3C,IACE,MAAM,KAAK,uBAAgB,CAAC,SAAS;YACrC,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,+BAAoB,GAAG,oBAAa,EAAE,CAAC,EAC1D,CAAC;YACD,OAAM;QACR,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,gDAAgD,YAAY,CAAC,EAAE,EAAE,CAClE,CAAA;QAED,IAAI,CAAC;YACH,mDAAmD;YACnD,MAAM,SAAS,GAAc,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,CAAA;YACzE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;YAEpE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,SAAS,CAAC,CAAA;gBACjE,OAAM;YACR,CAAC;YAED,uDAAuD;YACvD,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,EAAE,SAAS,CAAA;YACjD,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;gBAE5D,gEAAgE;gBAChE,mEAAmE;gBACnE,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;YACzD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,8DAA8D,CAC/D,CAAA;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;YACzD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,SAAiB,EAAE,MAAW;QAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mCAAmC,SAAS,EAAE,CAAC,CAAA;QAC/D,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAChC,IAAI,mCAAsB,CAAC;YACzB,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC/B,CAAC,CACH,CAAA;IACH,CAAC;CACF,CAAA;AAvEY,kDAAmB;8BAAnB,mBAAmB;IAF/B,IAAA,mBAAU,GAAE;IACZ,IAAA,mBAAY,EAAC,kDAAsB,CAAC;qCAOD,8BAAa;QAChB,0BAAmB;GAPvC,mBAAmB,CAuE/B"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImportStatusQueueEvent = void 0;
4
+ class ImportStatusQueueEvent {
5
+ fromSqsRecord(record) {
6
+ Object.assign(this, record, {
7
+ source: record.eventSourceARN,
8
+ });
9
+ return this;
10
+ }
11
+ }
12
+ exports.ImportStatusQueueEvent = ImportStatusQueueEvent;
13
+ //# sourceMappingURL=import-status.queue.event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-status.queue.event.js","sourceRoot":"","sources":["../../src/event/import-status.queue.event.ts"],"names":[],"mappings":";;;AAOA,MAAa,sBAAsB;IAYjC,aAAa,CAAC,MAAiB;QAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE;YAC1B,MAAM,EAAE,MAAM,CAAC,cAAc;SAC9B,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAlBD,wDAkBC"}
@@ -22,8 +22,10 @@ exports.ImportQueueEventHandler = void 0;
22
22
  */
23
23
  const core_1 = require("@mbc-cqrs-serverless/core");
24
24
  const common_1 = require("@nestjs/common");
25
+ const constant_1 = require("../constant");
25
26
  const comparison_status_enum_1 = require("../enum/comparison-status.enum");
26
27
  const import_status_enum_1 = require("../enum/import-status.enum");
28
+ const helpers_1 = require("../helpers");
27
29
  const import_module_definition_1 = require("../import.module-definition");
28
30
  const import_service_1 = require("../import.service");
29
31
  const import_queue_event_1 = require("./import.queue.event");
@@ -35,10 +37,8 @@ let ImportQueueEventHandler = ImportQueueEventHandler_1 = class ImportQueueEvent
35
37
  }
36
38
  async execute(event) {
37
39
  const importEntity = event.importEvent.importEntity;
38
- // This handler processes individual records, so it must ignore the master CSV jobs.
39
- // Master jobs are handled exclusively by the CsvImportQueueEventHandler.
40
- if (importEntity.type === 'CSV_MASTER_JOB') {
41
- this.logger.debug(`Skipping CSV_MASTER_JOB in main queue handler: ${importEntity.id}`);
40
+ if (!importEntity.id.startsWith(`${constant_1.IMPORT_PK_PREFIX}${core_1.KEY_SEPARATOR}`)) {
41
+ this.logger.debug(`Skipping other type import job in main queue handler: ${importEntity.id}`);
42
42
  return;
43
43
  }
44
44
  await this.handleImport(event);
@@ -48,7 +48,8 @@ let ImportQueueEventHandler = ImportQueueEventHandler_1 = class ImportQueueEvent
48
48
  */
49
49
  async handleImport(event) {
50
50
  const importKey = event.importEvent.importKey;
51
- const { attributes, tenantCode, type: tableName, } = event.importEvent.importEntity;
51
+ const importEntity = event.importEvent.importEntity;
52
+ const { attributes, tenantCode, type: tableName } = importEntity;
52
53
  this.logger.debug(`Processing import job ${importKey.pk}#${importKey.sk} for table: ${tableName}`);
53
54
  // 1. Find the correct strategies for this import's table type
54
55
  const strategy = this.strategyMap.get(tableName);
@@ -62,10 +63,16 @@ let ImportQueueEventHandler = ImportQueueEventHandler_1 = class ImportQueueEvent
62
63
  // 2. Set status to PROCESSING
63
64
  await this.importService.updateStatus(importKey, import_status_enum_1.ImportStatusEnum.PROCESSING);
64
65
  // 3. Execute all registered strategies in sequence for this record
65
- const result = await this.executeStrategy(strategy, attributes, tenantCode);
66
- // 4. Finalize the import status as COMPLETED
67
- await this.importService.updateStatus(importKey, import_status_enum_1.ImportStatusEnum.COMPLETED, { result });
68
- this.logger.log(`Successfully completed import job: ${importKey.pk}#${importKey.sk}`);
66
+ await this.executeStrategy(strategy, attributes, tenantCode, importEntity);
67
+ // // 4. Finalize the import status as COMPLETED
68
+ // await this.importService.updateStatus(
69
+ // importKey,
70
+ // ImportStatusEnum.COMPLETED,
71
+ // { result },
72
+ // )
73
+ // this.logger.log(
74
+ // `Successfully completed import job: ${importKey.pk}#${importKey.sk}`,
75
+ // )
69
76
  }
70
77
  catch (error) {
71
78
  // 5. Handle any errors during processing
@@ -86,29 +93,47 @@ let ImportQueueEventHandler = ImportQueueEventHandler_1 = class ImportQueueEvent
86
93
  * Executes the full lifecycle (compare, map, save) for a single strategy.
87
94
  * @returns The result of the create/update operation or a status message.
88
95
  */
89
- async executeStrategy(strategy, attributes, tenantCode) {
96
+ async executeStrategy(strategy, attributes, tenantCode, importEntity) {
90
97
  // 1. Determine if there are changes
91
98
  const compareResult = await strategy.compare(attributes, tenantCode);
99
+ const importKey = {
100
+ pk: importEntity.pk,
101
+ sk: importEntity.sk,
102
+ };
92
103
  if (compareResult.status === comparison_status_enum_1.ComparisonStatus.EQUAL) {
93
- return { status: 'EQUAL', message: 'No changes detected.' };
104
+ this.logger.log(`No changes for import job ${importEntity.id}, marking as completed.`);
105
+ await this.importService.updateStatus(importKey, import_status_enum_1.ImportStatusEnum.COMPLETED, { result: { status: 'EQUAL', message: 'No changes detected.' } });
106
+ const skParts = importEntity.sk.split(core_1.KEY_SEPARATOR);
107
+ const parentId = skParts.slice(0, -1).join(core_1.KEY_SEPARATOR);
108
+ if (parentId.startsWith(constant_1.CSV_IMPORT_PK_PREFIX)) {
109
+ this.logger.debug(`Updating parent job counter for EQUAL status child: ${importEntity.id}`);
110
+ const parentKey = (0, helpers_1.parseId)(parentId);
111
+ // Since the status is EQUAL, the child "succeeded" in its processing.
112
+ await this.importService.incrementParentJobCounters(parentKey, true);
113
+ }
114
+ return; // Stop execution for this case
94
115
  }
95
116
  // 2. Map the attributes to the correct CommandService input model
96
117
  // The strategy now handles the logic of building the payload.
97
118
  const mappedData = await strategy.map(compareResult.status, attributes, tenantCode, compareResult.existingData);
98
119
  const commandService = strategy.getCommandService();
99
- let finalResult;
120
+ let result;
100
121
  // 3. Execute the appropriate command
101
122
  const invokeContext = (0, core_1.extractInvokeContext)();
102
123
  const options = {
103
124
  invokeContext,
125
+ source: importEntity.id,
104
126
  };
105
127
  if (compareResult.status === comparison_status_enum_1.ComparisonStatus.NOT_EXIST) {
106
- finalResult = await commandService.publishAsync(mappedData, options);
128
+ result = await commandService.publishAsync(mappedData, options);
129
+ // 4. Finalize the import status as COMPLETED
130
+ await this.importService.updateStatus(importKey, import_status_enum_1.ImportStatusEnum.PROCESSING, { result: result });
131
+ this.logger.log(`Successfully completed import job: ${importKey.pk}#${importKey.sk}`);
107
132
  }
108
133
  else {
109
- finalResult = await commandService.publishPartialUpdateAsync(mappedData, options);
134
+ result = await commandService.publishPartialUpdateAsync(mappedData, options);
135
+ await this.importService.updateStatus(importKey, import_status_enum_1.ImportStatusEnum.PROCESSING, { result: result });
110
136
  }
111
- return finalResult;
112
137
  }
113
138
  };
114
139
  exports.ImportQueueEventHandler = ImportQueueEventHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"import.queue.event.handler.js","sourceRoot":"","sources":["../../src/event/import.queue.event.handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"import.queue.event.handler.js","sourceRoot":"","sources":["../../src/event/import.queue.event.handler.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export * from './command-finished.queue.event.handler';
1
2
  export * from './csv-import.queue.event.handler';
2
3
  export * from './csv-import.sfn.event';
3
4
  export * from './csv-import.sfn.event.handler';
@@ -5,3 +6,8 @@ export * from './import.event';
5
6
  export * from './import.event.handler';
6
7
  export * from './import.queue.event';
7
8
  export * from './import.queue.event.handler';
9
+ export * from './import-status.queue.event';
10
+ export * from './import-status.queue.event.handler';
11
+ export * from './zip-import.queue.event.handler';
12
+ export * from './zip-import.sfn.event';
13
+ export * from './zip-import.sfn.event.handler';
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./command-finished.queue.event.handler"), exports);
17
18
  __exportStar(require("./csv-import.queue.event.handler"), exports);
18
19
  __exportStar(require("./csv-import.sfn.event"), exports);
19
20
  __exportStar(require("./csv-import.sfn.event.handler"), exports);
@@ -21,4 +22,9 @@ __exportStar(require("./import.event"), exports);
21
22
  __exportStar(require("./import.event.handler"), exports);
22
23
  __exportStar(require("./import.queue.event"), exports);
23
24
  __exportStar(require("./import.queue.event.handler"), exports);
25
+ __exportStar(require("./import-status.queue.event"), exports);
26
+ __exportStar(require("./import-status.queue.event.handler"), exports);
27
+ __exportStar(require("./zip-import.queue.event.handler"), exports);
28
+ __exportStar(require("./zip-import.sfn.event"), exports);
29
+ __exportStar(require("./zip-import.sfn.event.handler"), exports);
24
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/event/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mEAAgD;AAChD,yDAAsC;AACtC,iEAA8C;AAC9C,iDAA8B;AAC9B,yDAAsC;AACtC,uDAAoC;AACpC,+DAA4C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/event/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yEAAsD;AACtD,mEAAgD;AAChD,yDAAsC;AACtC,iEAA8C;AAC9C,iDAA8B;AAC9B,yDAAsC;AACtC,uDAAoC;AACpC,+DAA4C;AAC5C,8DAA2C;AAC3C,sEAAmD;AACnD,mEAAgD;AAChD,yDAAsC;AACtC,iEAA8C"}
@@ -0,0 +1,25 @@
1
+ import { IEventHandler, S3Service, StepFunctionService } from '@mbc-cqrs-serverless/core';
2
+ import { ConfigService } from '@nestjs/config';
3
+ import { ImportService } from '../import.service';
4
+ import { ImportQueueEvent } from './import.queue.event';
5
+ export declare class ZipImportQueueEventHandler implements IEventHandler<ImportQueueEvent> {
6
+ private readonly configService;
7
+ private readonly sfnService;
8
+ private readonly importService;
9
+ private readonly s3Service;
10
+ private readonly logger;
11
+ private readonly zipOrchestratorArn;
12
+ constructor(configService: ConfigService, sfnService: StepFunctionService, importService: ImportService, s3Service: S3Service);
13
+ execute(event: ImportQueueEvent): Promise<any>;
14
+ private getS3Stream;
15
+ /**
16
+ * Helper function to convert a Readable stream into a Buffer.
17
+ * Required for yauzl, which operates on a complete data source.
18
+ */
19
+ private streamToBuffer;
20
+ /**
21
+ * Re-implemented using the `jszip` library, which is more tolerant
22
+ * of malformed ZIP archives.
23
+ */
24
+ private unzipAndUpload;
25
+ }
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var ZipImportQueueEventHandler_1;
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.ZipImportQueueEventHandler = void 0;
47
+ const client_s3_1 = require("@aws-sdk/client-s3");
48
+ const lib_storage_1 = require("@aws-sdk/lib-storage");
49
+ const core_1 = require("@mbc-cqrs-serverless/core");
50
+ const common_1 = require("@nestjs/common");
51
+ const config_1 = require("@nestjs/config");
52
+ const JSZip = __importStar(require("jszip"));
53
+ const stream_1 = require("stream");
54
+ const constant_1 = require("../constant");
55
+ const enum_1 = require("../enum");
56
+ const import_service_1 = require("../import.service");
57
+ const import_queue_event_1 = require("./import.queue.event");
58
+ let ZipImportQueueEventHandler = ZipImportQueueEventHandler_1 = class ZipImportQueueEventHandler {
59
+ constructor(configService, sfnService, importService, s3Service) {
60
+ this.configService = configService;
61
+ this.sfnService = sfnService;
62
+ this.importService = importService;
63
+ this.s3Service = s3Service;
64
+ this.logger = new common_1.Logger(ZipImportQueueEventHandler_1.name);
65
+ this.zipOrchestratorArn = this.configService.get('SFN_IMPORT_ZIP_ORCHESTRATOR_ARN');
66
+ }
67
+ async execute(event) {
68
+ const importEntity = event.importEvent.importEntity;
69
+ if (!importEntity.pk.startsWith(constant_1.ZIP_IMPORT_PK_PREFIX)) {
70
+ return;
71
+ }
72
+ const importKey = event.importEvent.importKey;
73
+ const zipJobAttributes = importEntity.attributes;
74
+ this.logger.log(`Received master ZIP job from queue: ${importEntity.id} for file ${zipJobAttributes.key}`);
75
+ try {
76
+ await this.importService.updateStatus(importKey, enum_1.ImportStatusEnum.PROCESSING, { result: { step: 'Unzipping archive' } });
77
+ const s3ReadStream = await this.getS3Stream(zipJobAttributes);
78
+ const extractedFileKeys = await this.unzipAndUpload(s3ReadStream, zipJobAttributes, importEntity.id);
79
+ if (extractedFileKeys.length === 0) {
80
+ throw new Error('No CSV files found in the ZIP archive.');
81
+ }
82
+ // Sort the file keys alphabetically to ensure sequential processing order
83
+ extractedFileKeys.sort();
84
+ await this.importService.updateImportJob(importKey, {
85
+ set: {
86
+ attributes: {
87
+ ...zipJobAttributes,
88
+ extractedFileKeys, // Save the list of files to the master job
89
+ },
90
+ },
91
+ });
92
+ // Start the main orchestrator with the sorted list of files
93
+ await this.sfnService.startExecution(this.zipOrchestratorArn, {
94
+ masterJobKey: importKey,
95
+ sortedS3Keys: extractedFileKeys,
96
+ // Pass through original attributes needed by the sub-workflows
97
+ parameters: {
98
+ bucket: zipJobAttributes.bucket,
99
+ tenantCode: zipJobAttributes.tenantCode,
100
+ },
101
+ }, `${zipJobAttributes.tenantCode}-zip-import-${Date.now()}`);
102
+ this.logger.log(`Started ZIP Orchestrator Step Function for master job ${importEntity.id}`);
103
+ }
104
+ catch (error) {
105
+ this.logger.error(`Failed to process ZIP job ${importEntity.id}`, error);
106
+ await this.importService.updateStatus(importKey, enum_1.ImportStatusEnum.FAILED, {
107
+ error: {
108
+ message: `Failed during unzip and preparation: ${error.message}`,
109
+ },
110
+ });
111
+ throw error;
112
+ }
113
+ }
114
+ async getS3Stream(attributes) {
115
+ const { Body: s3Stream } = await this.s3Service.client.send(new client_s3_1.GetObjectCommand({
116
+ Bucket: attributes.bucket,
117
+ Key: attributes.key,
118
+ }));
119
+ if (!(s3Stream instanceof stream_1.Readable)) {
120
+ throw new Error('Failed to get a readable stream from S3 object.');
121
+ }
122
+ return s3Stream;
123
+ }
124
+ /**
125
+ * Helper function to convert a Readable stream into a Buffer.
126
+ * Required for yauzl, which operates on a complete data source.
127
+ */
128
+ streamToBuffer(stream) {
129
+ return new Promise((resolve, reject) => {
130
+ const chunks = [];
131
+ stream.on('data', (chunk) => chunks.push(chunk));
132
+ stream.on('error', reject);
133
+ stream.on('end', () => resolve(Buffer.concat(chunks)));
134
+ });
135
+ }
136
+ /**
137
+ * Re-implemented using the `jszip` library, which is more tolerant
138
+ * of malformed ZIP archives.
139
+ */
140
+ async unzipAndUpload(zipStream, attributes, jobId) {
141
+ const tempS3Prefix = `unzipped/${attributes.tenantCode}/${jobId.replace(/[^a-zA-Z0-9]/g, '_')}`;
142
+ // 1. JSZip operates on a buffer, so we first load the stream into memory.
143
+ const zipBuffer = await this.streamToBuffer(zipStream);
144
+ // 2. Load the ZIP data.
145
+ const zip = await JSZip.loadAsync(zipBuffer);
146
+ const uploadPromises = [];
147
+ const extractedFileKeys = [];
148
+ // 3. Loop through each file in the archive.
149
+ for (const file of Object.values(zip.files)) {
150
+ // 4. Skip directories and process only CSV files.
151
+ if (!file.dir && file.name.toLowerCase().endsWith('.csv')) {
152
+ this.logger.debug(`Extracting ${file.name} ...`);
153
+ // 5. Decompress the file content into a buffer.
154
+ const contentBuffer = await file.async('nodebuffer');
155
+ const s3UploadKey = `${tempS3Prefix}/${file.name}`;
156
+ extractedFileKeys.push(s3UploadKey);
157
+ // 6. Create and track the S3 upload promise.
158
+ const upload = new lib_storage_1.Upload({
159
+ client: this.s3Service.client,
160
+ params: {
161
+ Bucket: attributes.bucket,
162
+ Key: s3UploadKey,
163
+ Body: contentBuffer,
164
+ },
165
+ });
166
+ uploadPromises.push(upload.done());
167
+ }
168
+ }
169
+ // 7. Wait for all files to be uploaded to S3.
170
+ await Promise.all(uploadPromises);
171
+ this.logger.log(`Finished unzipping with JSZip. Uploaded ${extractedFileKeys.length} CSV files.`);
172
+ return extractedFileKeys;
173
+ }
174
+ };
175
+ exports.ZipImportQueueEventHandler = ZipImportQueueEventHandler;
176
+ exports.ZipImportQueueEventHandler = ZipImportQueueEventHandler = ZipImportQueueEventHandler_1 = __decorate([
177
+ (0, core_1.EventHandler)(import_queue_event_1.ImportQueueEvent),
178
+ __metadata("design:paramtypes", [config_1.ConfigService,
179
+ core_1.StepFunctionService,
180
+ import_service_1.ImportService,
181
+ core_1.S3Service])
182
+ ], ZipImportQueueEventHandler);
183
+ //# sourceMappingURL=zip-import.queue.event.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip-import.queue.event.handler.js","sourceRoot":"","sources":["../../src/event/zip-import.queue.event.handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { IEvent, StepFunctionsContext } from '@mbc-cqrs-serverless/core';
2
+ export declare class ZipImportSfnEvent implements IEvent {
3
+ source: string;
4
+ context: StepFunctionsContext;
5
+ input: string | any[];
6
+ taskToken: string;
7
+ constructor(event?: Partial<ZipImportSfnEvent>);
8
+ }
@@ -0,0 +1,21 @@
1
+ import { IEventHandler } from '@mbc-cqrs-serverless/core';
2
+ import { ImportService } from '../import.service';
3
+ import { ZipImportSfnEvent } from './zip-import.sfn.event';
4
+ export declare class ZipImportSfnEventHandler implements IEventHandler<ZipImportSfnEvent> {
5
+ private readonly importService;
6
+ private readonly logger;
7
+ constructor(importService: ImportService);
8
+ execute(event: ZipImportSfnEvent): Promise<any>;
9
+ /**
10
+ * Handles the trigger_single_csv_and_wait state from the orchestrator.
11
+ * It extracts the tableName from the filename and starts a new CSV import job,
12
+ * passing along the taskToken so the orchestrator can be notified upon completion.
13
+ */
14
+ private triggerSingleCsvJob;
15
+ /**
16
+ * Handles the final state of the orchestrator.
17
+ * It aggregates the results from all processed CSV files and sets the final
18
+ * status on the original ZIP_MASTER_JOB.
19
+ */
20
+ private finalizeZipMasterJob;
21
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var ZipImportSfnEventHandler_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ZipImportSfnEventHandler = void 0;
14
+ const core_1 = require("@mbc-cqrs-serverless/core");
15
+ const common_1 = require("@nestjs/common");
16
+ const enum_1 = require("../enum");
17
+ const import_service_1 = require("../import.service");
18
+ const zip_import_sfn_event_1 = require("./zip-import.sfn.event");
19
+ let ZipImportSfnEventHandler = ZipImportSfnEventHandler_1 = class ZipImportSfnEventHandler {
20
+ constructor(importService) {
21
+ this.importService = importService;
22
+ this.logger = new common_1.Logger(ZipImportSfnEventHandler_1.name);
23
+ }
24
+ async execute(event) {
25
+ const stateName = event.context.State.Name;
26
+ this.logger.log(`Executing state: ${stateName} for Zip SFN`);
27
+ if (stateName === 'trigger_single_csv_and_wait') {
28
+ return this.triggerSingleCsvJob(event);
29
+ }
30
+ if (stateName === 'finalize_zip_job') {
31
+ return this.finalizeZipMasterJob(event);
32
+ }
33
+ this.logger.warn(`Unknown state name in ZipImportSfnEventHandler: ${stateName}`);
34
+ }
35
+ /**
36
+ * Handles the trigger_single_csv_and_wait state from the orchestrator.
37
+ * It extracts the tableName from the filename and starts a new CSV import job,
38
+ * passing along the taskToken so the orchestrator can be notified upon completion.
39
+ */
40
+ async triggerSingleCsvJob(event) {
41
+ const s3Key = event.input?.s3Key || event.input;
42
+ const { taskToken } = event;
43
+ const { masterJobKey, parameters } = event.context.Execution.Input;
44
+ this.logger.log(`Triggering CSV job for file: ${s3Key}`);
45
+ // Use a regex to extract the table name from the filename.
46
+ // Convention: yyyymmddhhMMss-{table name}.csv
47
+ const match = s3Key.match(/\d{14}-(.+)\.csv$/);
48
+ if (!match || !match[1]) {
49
+ throw new Error(`Could not parse tableName from filename: ${s3Key}. Expected format: yyyymmddhhMMss-{tableName}.csv`);
50
+ }
51
+ const tableName = match[1];
52
+ const dto = {
53
+ processingMode: enum_1.ProcessingMode.STEP_FUNCTION,
54
+ bucket: parameters.bucket,
55
+ key: s3Key,
56
+ tenantCode: parameters.tenantCode,
57
+ tableName: tableName,
58
+ };
59
+ await this.importService.createCsvJobWithTaskToken(dto, taskToken, masterJobKey);
60
+ this.logger.log(`Successfully created CSV job for ${tableName} with task token.`);
61
+ }
62
+ /**
63
+ * Handles the final state of the orchestrator.
64
+ * It aggregates the results from all processed CSV files and sets the final
65
+ * status on the original ZIP_MASTER_JOB.
66
+ */
67
+ async finalizeZipMasterJob(event) {
68
+ const resultsFromMapState = event.input?.processingResults ||
69
+ event.input; // This will be an array of results
70
+ const { masterJobKey } = event.context.Execution.Input;
71
+ this.logger.log(`Finalizing ZIP master job: ${masterJobKey.pk}#${masterJobKey.sk}`);
72
+ this.logger.debug('Aggregated results:', resultsFromMapState);
73
+ // Aggregate the results from each CSV file's processing.
74
+ const finalSummary = resultsFromMapState.reduce((acc, result) => {
75
+ const res = result?.result || result || {};
76
+ acc.totalRows += res.total || res.totalRows || 0;
77
+ acc.processedRows += res.succeeded || res.processedRows || 0;
78
+ acc.failedRows += res.failed || res.failedRows || 0;
79
+ return acc;
80
+ }, { totalRows: 0, processedRows: 0, failedRows: 0 });
81
+ const finalStatus = enum_1.ImportStatusEnum.COMPLETED;
82
+ await this.importService.updateStatus(masterJobKey, finalStatus, {
83
+ result: finalSummary,
84
+ });
85
+ this.logger.log(`Successfully finalized ZIP master job ${masterJobKey.pk}#${masterJobKey.sk} with status ${finalStatus}`);
86
+ }
87
+ };
88
+ exports.ZipImportSfnEventHandler = ZipImportSfnEventHandler;
89
+ exports.ZipImportSfnEventHandler = ZipImportSfnEventHandler = ZipImportSfnEventHandler_1 = __decorate([
90
+ (0, common_1.Injectable)(),
91
+ (0, core_1.EventHandler)(zip_import_sfn_event_1.ZipImportSfnEvent),
92
+ __metadata("design:paramtypes", [import_service_1.ImportService])
93
+ ], ZipImportSfnEventHandler);
94
+ //# sourceMappingURL=zip-import.sfn.event.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip-import.sfn.event.handler.js","sourceRoot":"","sources":["../../src/event/zip-import.sfn.event.handler.ts"],"names":[],"mappings":"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"}