@solidxai/core 0.1.1 → 0.1.2
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.
- package/dist/helpers/schematic.service.js +1 -1
- package/dist/helpers/schematic.service.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +2 -1
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +34 -9
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +2 -1
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +2 -1
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +14 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +192 -64
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/helpers/schematic.service.ts +1 -1
- package/src/seeders/module-metadata-seeder.service.ts +2 -1
- package/src/seeders/seed-data/solid-core-metadata.json +34 -9
- package/src/services/model-metadata.service.ts +2 -1
- package/src/services/module-metadata.service.ts +2 -1
- package/src/services/queues/rabbitmq-subscriber.service.ts +219 -95
|
@@ -194,7 +194,8 @@ let ModuleMetadataService = ModuleMetadataService_1 = class ModuleMetadataServic
|
|
|
194
194
|
sequenceNumber: 1,
|
|
195
195
|
actionUserKey: `${module?.name}-home-action`,
|
|
196
196
|
moduleUserKey: module?.name,
|
|
197
|
-
parentMenuItemUserKey: ""
|
|
197
|
+
parentMenuItemUserKey: "",
|
|
198
|
+
iconName: "home"
|
|
198
199
|
}
|
|
199
200
|
],
|
|
200
201
|
views: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-metadata.service.js","sourceRoot":"","sources":["../../src/services/module-metadata.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';\nimport { InjectDataSource, InjectRepository } from '@nestjs/typeorm';\nimport { DataSource, EntityManager, Repository, SelectQueryBuilder } from 'typeorm';\nimport { CreateModuleMetadataDto } from '../dtos/create-module-metadata.dto';\nimport { ModuleMetadata } from '../entities/module-metadata.entity';\nimport type { SolidCoreSetting } from \"src/services/settings/default-settings-provider.service\";\n\nimport { classify, dasherize } from '@angular-devkit/core/src/utils/strings';\nimport { ConfigService } from '@nestjs/config';\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport * as path from 'path'; // To handle file paths\nimport { PermissionMetadataSeederService } from 'src/seeders/permission-metadata-seeder.service';\nimport { DiskFileService } from 'src/services/file';\nimport { BasicFilterDto } from '../dtos/basic-filters.dto';\nimport { UpdateModuleMetadataDto } from '../dtos/update-module-metadata.dto';\nimport {\n ADD_MODULE_COMMAND,\n SchematicService,\n} from '../helpers/schematic.service';\nimport { SolidRegistry } from '../helpers/solid-registry';\nimport { CodeGenerationOptions, ModuleMetadataConfiguration } from '../interfaces';\nimport { CrudHelperService } from './crud-helper.service';\nimport { ModelMetadataService } from './model-metadata.service';\nimport { ModuleMetadataHelperService } from 'src/helpers/module-metadata-helper.service';\nimport { DisallowInProduction } from 'src/decorators/disallow-in-production.decorator';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport Module from 'module';\nimport { ModuleMetadataRepository } from 'src/repository/module-metadata.repository';\nimport { SettingService } from './setting.service';\n\n@Injectable()\nexport class ModuleMetadataService {\n private readonly logger = new Logger(ModuleMetadataService.name);\n\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n // @InjectRepository(ModuleMetadata)\n // private readonly moduleMetadataRepo: Repository<ModuleMetadata>,\n private readonly moduleMetadataRepo: ModuleMetadataRepository,\n private readonly crudHelperService: CrudHelperService,\n private readonly schematicService: SchematicService,\n private readonly configService: ConfigService,\n private readonly fileService: DiskFileService,\n private readonly settingService: SettingService,\n\n private readonly permissionsSeederService: PermissionMetadataSeederService,\n @Inject(forwardRef(() => ModelMetadataService))\n private readonly modelMetadataService: ModelMetadataService,\n private readonly solidRegistry: SolidRegistry,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n ) { }\n\n async findMany(basicFilterDto: BasicFilterDto) {\n const alias = 'moduleMetadata';\n // Extract the required keys from the input query\n let { limit, offset } = basicFilterDto;\n\n // Create above query on pincode table using query builder\n var qb: SelectQueryBuilder<ModuleMetadata> = await this.moduleMetadataRepo.createSecurityRuleAwareQueryBuilder(alias)\n qb = await this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n\n // Get the records and the count\n const [entities, count] = await qb.getManyAndCount();\n\n const currentPage = Math.floor(offset / limit) + 1;\n const totalPages = Math.ceil(count / limit);\n\n const nextPage = currentPage < totalPages ? currentPage + 1 : null;\n const prevPage = currentPage > 1 ? currentPage - 1 : null;\n\n const r = {\n meta: {\n totalRecords: count,\n currentPage: currentPage,\n nextPage: nextPage,\n prevPage: prevPage,\n totalPages: totalPages,\n perPage: +limit,\n },\n records: entities\n };\n return r\n }\n\n async find(basicFilterDto: BasicFilterDto) {\n return this.findMany(basicFilterDto);\n }\n\n async findOneByUserKey(name: string, relations = {}) {\n if (!name) {\n throw new BadRequestException(ERROR_MESSAGES.ENTITY_NAME_REQUIRED);\n }\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n name: name,\n },\n relations: relations,\n });\n return entity;\n }\n\n async findOne(id: number, relations = {}) {\n if (!id) {\n throw new BadRequestException(ERROR_MESSAGES.ENTITY_ID_REQUIRED);\n }\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n id: id,\n },\n relations: relations,\n });\n if (!entity) {\n throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND());\n }\n return entity;\n }\n\n async create(createDto: CreateModuleMetadataDto, files: Express.Multer.File[] = []) {\n try {\n return await this.dataSource.transaction(async (manager: EntityManager) => {\n // Step 1: Write initial data to the database\n const module = await this.createInDB(manager, createDto, files);\n await this.createInFile(module);\n return module\n });\n } catch (error) {\n // console.error('Transaction failed:', error);\n this.logger.error('Transaction failed:', error);\n throw error;\n }\n }\n\n async createInDB(manager: EntityManager, createDto: CreateModuleMetadataDto, files: Express.Multer.File[] = []) {\n if (files.length > 0) {\n const fileStoragePath = await this.getFileSysytemFullFilePath(this.getFileName(files[0]));\n this.fileService.copy(files[0].path, fileStoragePath);\n this.fileService.delete(files[0].path);\n createDto.menuIconUrl = fileStoragePath;\n }\n const moduleMetadata = this.moduleMetadataRepo.create(createDto);\n return manager.save(moduleMetadata); // Use the provided manager to perform DB operations\n }\n\n async createInFile(module: ModuleMetadata) {\n try {\n // Prepare the metadata JSON structure\n\n const moduleMetaDataJson: ModuleMetadataConfiguration = {\n moduleMetadata: {\n name: module?.name,\n displayName: module?.displayName,\n description: module?.description,\n defaultDataSource: module?.defaultDataSource,\n menuIconUrl: module?.menuIconUrl,\n menuSequenceNumber: module?.menuSequenceNumber,\n isSystem: module?.isSystem,\n models: [],\n },\n roles: [],\n users: [],\n actions: [\n {\n displayName: `${module?.name} Home`,\n name: `${module?.name}-home-action`,\n type: \"custom\",\n domain: \"\",\n context: \"\",\n customComponent: `/admin/core/${module?.name}/home`,\n customIsModal: true,\n serverEndpoint: \"\",\n viewUserKey: \"\",\n moduleUserKey: module?.name,\n modelUserKey: \"\"\n }\n ],\n menus: [\n {\n displayName: \"Home\",\n name: `${module?.name}-home-menu`,\n sequenceNumber: 1,\n actionUserKey: `${module?.name}-home-action`,\n moduleUserKey: module?.name,\n parentMenuItemUserKey: \"\"\n }\n ],\n views: [],\n emailTemplates: [],\n smsTemplates: [],\n mediaStorageProviders: [],\n securityRules: [],\n };\n\n // Convert the object to JSON string\n const metadataJson = JSON.stringify(moduleMetaDataJson, null, 2);\n\n // Create the folder path inside 'module-metadata'\n const folderPath = path.resolve(process.cwd(), 'module-metadata', module.name);\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(module.name);\n\n // Ensure the folder exists\n await fs.mkdir(folderPath, { recursive: true });\n\n // Write the JSON to the file\n await fs.writeFile(filePath, metadataJson);\n\n } catch (error) {\n // console.error('File creation failed:', error);\n this.logger.error('File creation failed:', error);\n throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback\n }\n }\n\n async update(id: number, updateModuleMetadataDto: UpdateModuleMetadataDto, files: Express.Multer.File[] = []) {\n try {\n return await this.dataSource.transaction(async (manager: EntityManager) => {\n // Step 1: Write initial data to the database\n const module = await this.updateInDB(manager, id, updateModuleMetadataDto, files);\n await this.updateInFile(module);\n return module\n });\n } catch (error) {\n // console.error('Transaction failed:', error);\n this.logger.error('Transaction failed:', error);\n throw error;\n }\n }\n\n async updateInDB(manager: EntityManager, id: number, updateModuleMetadataDto: UpdateModuleMetadataDto, files: Express.Multer.File[] = []) {\n\n const module = await this.moduleMetadataRepo.preload({\n id,\n ...updateModuleMetadataDto,\n });\n\n if (!module) {\n throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(id));\n }\n if (files.length > 0) {\n\n const fileStoragePath = await this.getFileSysytemFullFilePath(this.getFileName(files[0]));\n this.fileService.copy(files[0].path, fileStoragePath);\n this.fileService.delete(files[0].path);\n module.menuIconUrl = fileStoragePath;\n }\n return manager.save(ModuleMetadata, module);\n }\n\n async updateInFile(module: ModuleMetadata) {\n try {\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(module.name);\n\n // Read the existing JSON file\n let metaData;\n try {\n metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);\n\n } catch (error) {\n metaData = {\n moduleMetadata: {\n name: null,\n displayName: null,\n description: null,\n defaultDataSource: null,\n menuIconUrl: null,\n menuSequenceNumber: null,\n isSystem: null,\n models: [],\n },\n roles: [],\n users: [],\n actions: [],\n menus: [],\n views: [],\n emailTemplates: [],\n smsTemplates: [],\n mediaStorageProviders: [],\n };\n }\n\n\n metaData.moduleMetadata.name = module?.name;\n metaData.moduleMetadata.displayName = module?.displayName;\n metaData.moduleMetadata.description = module?.description;\n metaData.moduleMetadata.defaultDataSource = module?.defaultDataSource;\n metaData.moduleMetadata.menuIconUrl = module?.menuIconUrl;\n metaData.moduleMetadata.menuSequenceNumber = module?.menuSequenceNumber;\n metaData.moduleMetadata.isSystem = module?.isSystem;\n\n // Write the JSON to the file\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n\n } catch (error) {\n // console.error('File creation failed:', error);\n this.logger.error('File creation failed:', error);\n throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback\n }\n }\n\n async upsert(updateModuleMetadataDto: UpdateModuleMetadataDto) {\n this.logger.debug(`Module Upsert called for : ${updateModuleMetadataDto.name}`);\n // First check if module already exists using name\n const existingModuleMetadata = await this.moduleMetadataRepo.findOne({\n where: {\n name: updateModuleMetadataDto.name\n }\n })\n const { models, ...restUpdateModuleMetadataDto } = updateModuleMetadataDto;\n // if found\n if (existingModuleMetadata) {\n const updatedModuleMetadata = { ...existingModuleMetadata, ...restUpdateModuleMetadataDto };\n return this.moduleMetadataRepo.save(updatedModuleMetadata);\n }\n // if not found - create new \n else {\n const moduleMetadata = this.moduleMetadataRepo.create(restUpdateModuleMetadataDto);\n return this.moduleMetadataRepo.save(moduleMetadata);\n }\n }\n\n async removeByName(name: string) {\n const entity = await this.findOneByUserKey(name);\n if (entity) {\n await this.moduleMetadataRepo.remove(entity);\n }\n }\n\n async remove(id: number) {\n const entity = await this.findOne(id);\n await this.cleanupOnDelete(entity.id);\n const r = await this.moduleMetadataRepo.remove(entity);\n return r\n\n }\n\n\n async cleanupOnDelete(moduleEntityId: number) {\n const moduleEntity = await this.moduleMetadataRepo.findOne({\n where: {\n // @ts-ignore\n id: moduleEntityId,\n }\n });\n\n if (!moduleEntity) {\n this.logger.log(`Invalid moduleEntityId: ${moduleEntityId} unable to resolve model metadata`);\n return;\n }\n if (moduleEntity.id !== moduleEntityId) {\n this.logger.log(`Invalid moduleEntityId: ${moduleEntityId} unable to resolve model metadata id ${moduleEntity.id} not matching with the one passed as argument ${moduleEntityId}`);\n return;\n }\n\n this.logger.log(`Cleaning up for module: ${moduleEntity.name}.`);\n\n const modulePath = await this.moduleMetadataHelperService.getModulePath(moduleEntity.name);\n if (modulePath) {\n\n this.logger.log(`Module path: ${modulePath}`);\n\n // Metadata file to be deleted\n const moduleMetadataPAth = await this.moduleMetadataHelperService.getModuleMetadataFolderPath(moduleEntity.name)\n this.logger.log(`About to delete module metadata path: ${moduleMetadataPAth}`);\n\n try {\n await fs.rm(modulePath, { recursive: true, force: true });\n await fs.rm(moduleMetadataPAth, { recursive: true, force: true });\n this.logger.log(`Deleted file: ${moduleMetadataPAth}`);\n } catch (error) {\n this.logger.error(`Error deleting file: ${moduleMetadataPAth}`, error);\n throw new Error(ERROR_MESSAGES.FILE_DELETE_FAILED); // Trigger rollback\n }\n }\n await this.dataSource.query(\n `CALL cleanup_module_metadata($1, $2)`,\n [moduleEntity.name, true],\n );\n }\n\n async deleteMany(ids: number[]): Promise<any> {\n if (!ids || ids.length === 0) {\n throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);\n }\n const removedEntities = [];\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i]\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n // if (!entity) {\n // throw new Error(`Entity with id ${id} not found`);\n // }\n removedEntities.push(await this.moduleMetadataRepo.remove(entity));\n }\n\n return removedEntities\n }\n\n async refreshPermission() {\n await this.permissionsSeederService.seed();\n return true\n }\n\n @DisallowInProduction()\n async generateCode(options: CodeGenerationOptions): Promise<string> {\n if (!options.moduleId && !options.moduleUserKey) {\n throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);\n }\n const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);\n\n // Check if the module exists\n if (!module) {\n throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(options.moduleId));\n }\n\n // Check if the module name already exists and is loaded\n const moduleInstance = this.solidRegistry.getModule(`${classify(module.name)}Module`);\n\n if (!moduleInstance) {\n const addModuleOutput = await this.generateAddModuleCode(options);\n const refreshModuleOutput = await this.generateRefreshModuleCode(options);\n return `${addModuleOutput}\\n${refreshModuleOutput}`;\n } else {\n return await this.generateRefreshModuleCode(options);\n }\n }\n\n private async generateAddModuleCode(options: CodeGenerationOptions = { dryRun: false }): Promise<string> {\n if (!options.moduleId && !options.moduleUserKey) {\n throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);\n }\n const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);\n\n //Generate the module\n const output = await this.schematicService.executeSchematicCommand(\n ADD_MODULE_COMMAND,\n { module: module.name },\n options.dryRun ?? false\n );\n this.logger.debug(`Schematic output : ${output}`);\n return output;\n }\n\n private async generateRefreshModuleCode(options: CodeGenerationOptions): Promise<string> {\n const query = {\n relations: { models: { fields: true } },\n };\n const module = options.moduleId ? await this.findOne(options.moduleId, query.relations) : await this.findOneByUserKey(options.moduleUserKey, query.relations);\n const outputLines = []\n for (const model of module.models) {\n const codeGenerationOptions = {\n modelId: model.id,\n dryRun: options.dryRun,\n };\n const output = await this.modelMetadataService.handleGenerateCode(codeGenerationOptions);\n this.logger.debug(`Schematic output : ${output}`);\n outputLines.push(output)\n }\n return outputLines.join('\\n');\n }\n\n private async getFileSysytemFullFilePath(fileName: string): Promise<string> {\n const fileStorageDir = this.settingService.getConfigValue<SolidCoreSetting>(\"fileStorageDir\")\n return `${fileStorageDir}/${fileName}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"module-metadata.service.js","sourceRoot":"","sources":["../../src/services/module-metadata.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';\nimport { InjectDataSource, InjectRepository } from '@nestjs/typeorm';\nimport { DataSource, EntityManager, Repository, SelectQueryBuilder } from 'typeorm';\nimport { CreateModuleMetadataDto } from '../dtos/create-module-metadata.dto';\nimport { ModuleMetadata } from '../entities/module-metadata.entity';\nimport type { SolidCoreSetting } from \"src/services/settings/default-settings-provider.service\";\n\nimport { classify, dasherize } from '@angular-devkit/core/src/utils/strings';\nimport { ConfigService } from '@nestjs/config';\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport * as path from 'path'; // To handle file paths\nimport { PermissionMetadataSeederService } from 'src/seeders/permission-metadata-seeder.service';\nimport { DiskFileService } from 'src/services/file';\nimport { BasicFilterDto } from '../dtos/basic-filters.dto';\nimport { UpdateModuleMetadataDto } from '../dtos/update-module-metadata.dto';\nimport {\n ADD_MODULE_COMMAND,\n SchematicService,\n} from '../helpers/schematic.service';\nimport { SolidRegistry } from '../helpers/solid-registry';\nimport { CodeGenerationOptions, ModuleMetadataConfiguration } from '../interfaces';\nimport { CrudHelperService } from './crud-helper.service';\nimport { ModelMetadataService } from './model-metadata.service';\nimport { ModuleMetadataHelperService } from 'src/helpers/module-metadata-helper.service';\nimport { DisallowInProduction } from 'src/decorators/disallow-in-production.decorator';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport Module from 'module';\nimport { ModuleMetadataRepository } from 'src/repository/module-metadata.repository';\nimport { SettingService } from './setting.service';\n\n@Injectable()\nexport class ModuleMetadataService {\n private readonly logger = new Logger(ModuleMetadataService.name);\n\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n // @InjectRepository(ModuleMetadata)\n // private readonly moduleMetadataRepo: Repository<ModuleMetadata>,\n private readonly moduleMetadataRepo: ModuleMetadataRepository,\n private readonly crudHelperService: CrudHelperService,\n private readonly schematicService: SchematicService,\n private readonly configService: ConfigService,\n private readonly fileService: DiskFileService,\n private readonly settingService: SettingService,\n\n private readonly permissionsSeederService: PermissionMetadataSeederService,\n @Inject(forwardRef(() => ModelMetadataService))\n private readonly modelMetadataService: ModelMetadataService,\n private readonly solidRegistry: SolidRegistry,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n ) { }\n\n async findMany(basicFilterDto: BasicFilterDto) {\n const alias = 'moduleMetadata';\n // Extract the required keys from the input query\n let { limit, offset } = basicFilterDto;\n\n // Create above query on pincode table using query builder\n var qb: SelectQueryBuilder<ModuleMetadata> = await this.moduleMetadataRepo.createSecurityRuleAwareQueryBuilder(alias)\n qb = await this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n\n // Get the records and the count\n const [entities, count] = await qb.getManyAndCount();\n\n const currentPage = Math.floor(offset / limit) + 1;\n const totalPages = Math.ceil(count / limit);\n\n const nextPage = currentPage < totalPages ? currentPage + 1 : null;\n const prevPage = currentPage > 1 ? currentPage - 1 : null;\n\n const r = {\n meta: {\n totalRecords: count,\n currentPage: currentPage,\n nextPage: nextPage,\n prevPage: prevPage,\n totalPages: totalPages,\n perPage: +limit,\n },\n records: entities\n };\n return r\n }\n\n async find(basicFilterDto: BasicFilterDto) {\n return this.findMany(basicFilterDto);\n }\n\n async findOneByUserKey(name: string, relations = {}) {\n if (!name) {\n throw new BadRequestException(ERROR_MESSAGES.ENTITY_NAME_REQUIRED);\n }\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n name: name,\n },\n relations: relations,\n });\n return entity;\n }\n\n async findOne(id: number, relations = {}) {\n if (!id) {\n throw new BadRequestException(ERROR_MESSAGES.ENTITY_ID_REQUIRED);\n }\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n id: id,\n },\n relations: relations,\n });\n if (!entity) {\n throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND());\n }\n return entity;\n }\n\n async create(createDto: CreateModuleMetadataDto, files: Express.Multer.File[] = []) {\n try {\n return await this.dataSource.transaction(async (manager: EntityManager) => {\n // Step 1: Write initial data to the database\n const module = await this.createInDB(manager, createDto, files);\n await this.createInFile(module);\n return module\n });\n } catch (error) {\n // console.error('Transaction failed:', error);\n this.logger.error('Transaction failed:', error);\n throw error;\n }\n }\n\n async createInDB(manager: EntityManager, createDto: CreateModuleMetadataDto, files: Express.Multer.File[] = []) {\n if (files.length > 0) {\n const fileStoragePath = await this.getFileSysytemFullFilePath(this.getFileName(files[0]));\n this.fileService.copy(files[0].path, fileStoragePath);\n this.fileService.delete(files[0].path);\n createDto.menuIconUrl = fileStoragePath;\n }\n const moduleMetadata = this.moduleMetadataRepo.create(createDto);\n return manager.save(moduleMetadata); // Use the provided manager to perform DB operations\n }\n\n async createInFile(module: ModuleMetadata) {\n try {\n // Prepare the metadata JSON structure\n\n const moduleMetaDataJson: ModuleMetadataConfiguration = {\n moduleMetadata: {\n name: module?.name,\n displayName: module?.displayName,\n description: module?.description,\n defaultDataSource: module?.defaultDataSource,\n menuIconUrl: module?.menuIconUrl,\n menuSequenceNumber: module?.menuSequenceNumber,\n isSystem: module?.isSystem,\n models: [],\n },\n roles: [],\n users: [],\n actions: [\n {\n displayName: `${module?.name} Home`,\n name: `${module?.name}-home-action`,\n type: \"custom\",\n domain: \"\",\n context: \"\",\n customComponent: `/admin/core/${module?.name}/home`,\n customIsModal: true,\n serverEndpoint: \"\",\n viewUserKey: \"\",\n moduleUserKey: module?.name,\n modelUserKey: \"\"\n }\n ],\n menus: [\n {\n displayName: \"Home\",\n name: `${module?.name}-home-menu`,\n sequenceNumber: 1,\n actionUserKey: `${module?.name}-home-action`,\n moduleUserKey: module?.name,\n parentMenuItemUserKey: \"\",\n iconName : \"home\"\n }\n ],\n views: [],\n emailTemplates: [],\n smsTemplates: [],\n mediaStorageProviders: [],\n securityRules: [],\n };\n\n // Convert the object to JSON string\n const metadataJson = JSON.stringify(moduleMetaDataJson, null, 2);\n\n // Create the folder path inside 'module-metadata'\n const folderPath = path.resolve(process.cwd(), 'module-metadata', module.name);\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(module.name);\n\n // Ensure the folder exists\n await fs.mkdir(folderPath, { recursive: true });\n\n // Write the JSON to the file\n await fs.writeFile(filePath, metadataJson);\n\n } catch (error) {\n // console.error('File creation failed:', error);\n this.logger.error('File creation failed:', error);\n throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback\n }\n }\n\n async update(id: number, updateModuleMetadataDto: UpdateModuleMetadataDto, files: Express.Multer.File[] = []) {\n try {\n return await this.dataSource.transaction(async (manager: EntityManager) => {\n // Step 1: Write initial data to the database\n const module = await this.updateInDB(manager, id, updateModuleMetadataDto, files);\n await this.updateInFile(module);\n return module\n });\n } catch (error) {\n // console.error('Transaction failed:', error);\n this.logger.error('Transaction failed:', error);\n throw error;\n }\n }\n\n async updateInDB(manager: EntityManager, id: number, updateModuleMetadataDto: UpdateModuleMetadataDto, files: Express.Multer.File[] = []) {\n\n const module = await this.moduleMetadataRepo.preload({\n id,\n ...updateModuleMetadataDto,\n });\n\n if (!module) {\n throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(id));\n }\n if (files.length > 0) {\n\n const fileStoragePath = await this.getFileSysytemFullFilePath(this.getFileName(files[0]));\n this.fileService.copy(files[0].path, fileStoragePath);\n this.fileService.delete(files[0].path);\n module.menuIconUrl = fileStoragePath;\n }\n return manager.save(ModuleMetadata, module);\n }\n\n async updateInFile(module: ModuleMetadata) {\n try {\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(module.name);\n\n // Read the existing JSON file\n let metaData;\n try {\n metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);\n\n } catch (error) {\n metaData = {\n moduleMetadata: {\n name: null,\n displayName: null,\n description: null,\n defaultDataSource: null,\n menuIconUrl: null,\n menuSequenceNumber: null,\n isSystem: null,\n models: [],\n },\n roles: [],\n users: [],\n actions: [],\n menus: [],\n views: [],\n emailTemplates: [],\n smsTemplates: [],\n mediaStorageProviders: [],\n };\n }\n\n\n metaData.moduleMetadata.name = module?.name;\n metaData.moduleMetadata.displayName = module?.displayName;\n metaData.moduleMetadata.description = module?.description;\n metaData.moduleMetadata.defaultDataSource = module?.defaultDataSource;\n metaData.moduleMetadata.menuIconUrl = module?.menuIconUrl;\n metaData.moduleMetadata.menuSequenceNumber = module?.menuSequenceNumber;\n metaData.moduleMetadata.isSystem = module?.isSystem;\n\n // Write the JSON to the file\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n\n } catch (error) {\n // console.error('File creation failed:', error);\n this.logger.error('File creation failed:', error);\n throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback\n }\n }\n\n async upsert(updateModuleMetadataDto: UpdateModuleMetadataDto) {\n this.logger.debug(`Module Upsert called for : ${updateModuleMetadataDto.name}`);\n // First check if module already exists using name\n const existingModuleMetadata = await this.moduleMetadataRepo.findOne({\n where: {\n name: updateModuleMetadataDto.name\n }\n })\n const { models, ...restUpdateModuleMetadataDto } = updateModuleMetadataDto;\n // if found\n if (existingModuleMetadata) {\n const updatedModuleMetadata = { ...existingModuleMetadata, ...restUpdateModuleMetadataDto };\n return this.moduleMetadataRepo.save(updatedModuleMetadata);\n }\n // if not found - create new \n else {\n const moduleMetadata = this.moduleMetadataRepo.create(restUpdateModuleMetadataDto);\n return this.moduleMetadataRepo.save(moduleMetadata);\n }\n }\n\n async removeByName(name: string) {\n const entity = await this.findOneByUserKey(name);\n if (entity) {\n await this.moduleMetadataRepo.remove(entity);\n }\n }\n\n async remove(id: number) {\n const entity = await this.findOne(id);\n await this.cleanupOnDelete(entity.id);\n const r = await this.moduleMetadataRepo.remove(entity);\n return r\n\n }\n\n\n async cleanupOnDelete(moduleEntityId: number) {\n const moduleEntity = await this.moduleMetadataRepo.findOne({\n where: {\n // @ts-ignore\n id: moduleEntityId,\n }\n });\n\n if (!moduleEntity) {\n this.logger.log(`Invalid moduleEntityId: ${moduleEntityId} unable to resolve model metadata`);\n return;\n }\n if (moduleEntity.id !== moduleEntityId) {\n this.logger.log(`Invalid moduleEntityId: ${moduleEntityId} unable to resolve model metadata id ${moduleEntity.id} not matching with the one passed as argument ${moduleEntityId}`);\n return;\n }\n\n this.logger.log(`Cleaning up for module: ${moduleEntity.name}.`);\n\n const modulePath = await this.moduleMetadataHelperService.getModulePath(moduleEntity.name);\n if (modulePath) {\n\n this.logger.log(`Module path: ${modulePath}`);\n\n // Metadata file to be deleted\n const moduleMetadataPAth = await this.moduleMetadataHelperService.getModuleMetadataFolderPath(moduleEntity.name)\n this.logger.log(`About to delete module metadata path: ${moduleMetadataPAth}`);\n\n try {\n await fs.rm(modulePath, { recursive: true, force: true });\n await fs.rm(moduleMetadataPAth, { recursive: true, force: true });\n this.logger.log(`Deleted file: ${moduleMetadataPAth}`);\n } catch (error) {\n this.logger.error(`Error deleting file: ${moduleMetadataPAth}`, error);\n throw new Error(ERROR_MESSAGES.FILE_DELETE_FAILED); // Trigger rollback\n }\n }\n await this.dataSource.query(\n `CALL cleanup_module_metadata($1, $2)`,\n [moduleEntity.name, true],\n );\n }\n\n async deleteMany(ids: number[]): Promise<any> {\n if (!ids || ids.length === 0) {\n throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);\n }\n const removedEntities = [];\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i]\n const entity = await this.moduleMetadataRepo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n // if (!entity) {\n // throw new Error(`Entity with id ${id} not found`);\n // }\n removedEntities.push(await this.moduleMetadataRepo.remove(entity));\n }\n\n return removedEntities\n }\n\n async refreshPermission() {\n await this.permissionsSeederService.seed();\n return true\n }\n\n @DisallowInProduction()\n async generateCode(options: CodeGenerationOptions): Promise<string> {\n if (!options.moduleId && !options.moduleUserKey) {\n throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);\n }\n const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);\n\n // Check if the module exists\n if (!module) {\n throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(options.moduleId));\n }\n\n // Check if the module name already exists and is loaded\n const moduleInstance = this.solidRegistry.getModule(`${classify(module.name)}Module`);\n\n if (!moduleInstance) {\n const addModuleOutput = await this.generateAddModuleCode(options);\n const refreshModuleOutput = await this.generateRefreshModuleCode(options);\n return `${addModuleOutput}\\n${refreshModuleOutput}`;\n } else {\n return await this.generateRefreshModuleCode(options);\n }\n }\n\n private async generateAddModuleCode(options: CodeGenerationOptions = { dryRun: false }): Promise<string> {\n if (!options.moduleId && !options.moduleUserKey) {\n throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);\n }\n const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);\n\n //Generate the module\n const output = await this.schematicService.executeSchematicCommand(\n ADD_MODULE_COMMAND,\n { module: module.name },\n options.dryRun ?? false\n );\n this.logger.debug(`Schematic output : ${output}`);\n return output;\n }\n\n private async generateRefreshModuleCode(options: CodeGenerationOptions): Promise<string> {\n const query = {\n relations: { models: { fields: true } },\n };\n const module = options.moduleId ? await this.findOne(options.moduleId, query.relations) : await this.findOneByUserKey(options.moduleUserKey, query.relations);\n const outputLines = []\n for (const model of module.models) {\n const codeGenerationOptions = {\n modelId: model.id,\n dryRun: options.dryRun,\n };\n const output = await this.modelMetadataService.handleGenerateCode(codeGenerationOptions);\n this.logger.debug(`Schematic output : ${output}`);\n outputLines.push(output)\n }\n return outputLines.join('\\n');\n }\n\n private async getFileSysytemFullFilePath(fileName: string): Promise<string> {\n const fileStorageDir = this.settingService.getConfigValue<SolidCoreSetting>(\"fileStorageDir\")\n return `${fileStorageDir}/${fileName}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n\n}\n"]}
|
|
@@ -10,13 +10,26 @@ export declare abstract class RabbitMqSubscriber<T> implements OnModuleInit, Que
|
|
|
10
10
|
private readonly logger;
|
|
11
11
|
private readonly url;
|
|
12
12
|
private readonly serviceRole;
|
|
13
|
+
private connection;
|
|
14
|
+
private channel;
|
|
15
|
+
private consumerTag;
|
|
16
|
+
private reconnectPromise;
|
|
17
|
+
private reconnectAttempt;
|
|
18
|
+
private stopping;
|
|
13
19
|
constructor(mqMessageService: MqMessageService, mqMessageQueueService: MqMessageQueueService);
|
|
14
20
|
abstract subscribe(message: QueueMessage<T>): any;
|
|
15
21
|
abstract options(): QueuesModuleOptions;
|
|
16
22
|
establishConnection(): Promise<amqp.Connection>;
|
|
17
23
|
onModuleInit(): Promise<void>;
|
|
24
|
+
private connectAndConsume;
|
|
25
|
+
private handleProcessingError;
|
|
26
|
+
private publishToFailedQueue;
|
|
27
|
+
private triggerReconnect;
|
|
28
|
+
private reconnectLoop;
|
|
29
|
+
private cleanup;
|
|
30
|
+
private sleep;
|
|
31
|
+
private backoff;
|
|
18
32
|
protected processMessage(message: QueueMessage<T>, rawMessage: any, channel: any): Promise<void>;
|
|
19
|
-
private retryMessage;
|
|
20
33
|
private updateStatusInDatabase;
|
|
21
34
|
}
|
|
22
35
|
//# sourceMappingURL=rabbitmq-subscriber.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-subscriber.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,8BAAsB,kBAAkB,CAAC,CAAC,CAAE,YAAW,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"rabbitmq-subscriber.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,8BAAsB,kBAAkB,CAAC,CAAC,CAAE,YAAW,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC;IAWvE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB;IAAE,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IAVlI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAS;gBAEM,gBAAgB,EAAE,gBAAgB,EAAqB,qBAAqB,EAAE,qBAAqB;IAYlI,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3C,QAAQ,CAAC,OAAO,IAAI,mBAAmB;IAEjC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAsB/C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YAoCrB,iBAAiB;YAkGjB,qBAAqB;YA8BrB,oBAAoB;IAclC,OAAO,CAAC,gBAAgB;YAWV,aAAa;YAkBb,OAAO;IAkCrB,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,OAAO;cAWC,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,UAAU,KAAA,EAAE,OAAO,KAAA,GAAG,OAAO,CAAC,IAAI,CAAC;YAc9E,sBAAsB;CAkCvC"}
|
|
@@ -41,6 +41,12 @@ class RabbitMqSubscriber {
|
|
|
41
41
|
this.mqMessageService = mqMessageService;
|
|
42
42
|
this.mqMessageQueueService = mqMessageQueueService;
|
|
43
43
|
this.logger = new common_1.Logger(RabbitMqSubscriber.name);
|
|
44
|
+
this.connection = null;
|
|
45
|
+
this.channel = null;
|
|
46
|
+
this.consumerTag = null;
|
|
47
|
+
this.reconnectPromise = null;
|
|
48
|
+
this.reconnectAttempt = 0;
|
|
49
|
+
this.stopping = false;
|
|
44
50
|
this.url = process.env.QUEUES_RABBIT_MQ_URL;
|
|
45
51
|
this.serviceRole = process.env.QUEUES_SERVICE_ROLE;
|
|
46
52
|
if (!this.url) {
|
|
@@ -59,6 +65,7 @@ class RabbitMqSubscriber {
|
|
|
59
65
|
username: url.username,
|
|
60
66
|
password: decodeURIComponent(url.password),
|
|
61
67
|
frameMax: 131072,
|
|
68
|
+
heartbeat: 30,
|
|
62
69
|
});
|
|
63
70
|
return connection;
|
|
64
71
|
}
|
|
@@ -82,83 +89,204 @@ class RabbitMqSubscriber {
|
|
|
82
89
|
return;
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
|
-
let connection;
|
|
86
92
|
try {
|
|
87
|
-
|
|
93
|
+
await this.connectAndConsume(queueName);
|
|
88
94
|
}
|
|
89
95
|
catch (err) {
|
|
90
|
-
this.logger.error(`Failed to connect to RabbitMQ: ${err.message}`, err.stack);
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
const channel = await connection.createChannel();
|
|
94
|
-
const exchangeName = `${queueName}.exchange`;
|
|
95
|
-
const routingKey = `${queueName}.routing-key`;
|
|
96
|
-
await channel.assertExchange(exchangeName, 'direct', {});
|
|
97
|
-
const queue = await channel.assertQueue(queueName, {});
|
|
98
|
-
await channel.bindQueue(queue.queue, exchangeName, routingKey);
|
|
99
|
-
channel.consume(queue.queue, async (rawMessage) => {
|
|
100
|
-
if (rawMessage) {
|
|
101
|
-
const messageContentString = rawMessage.content.toString();
|
|
102
|
-
let message = null;
|
|
103
|
-
try {
|
|
104
|
-
message = JSON.parse(messageContentString);
|
|
105
|
-
if (!message.retryCount)
|
|
106
|
-
message.retryCount = 0;
|
|
107
|
-
if (!message.retryInterval)
|
|
108
|
-
message.retryInterval = 1000;
|
|
109
|
-
if (!message.currentRetry)
|
|
110
|
-
message.currentRetry = 0;
|
|
111
|
-
await this.processMessage(message, rawMessage, channel);
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
this.logger.error(`Error processing message: ${error.message}`);
|
|
115
|
-
if (message) {
|
|
116
|
-
if (message.currentRetry < message.retryCount) {
|
|
117
|
-
await this.updateStatusInDatabase('retrying', message);
|
|
118
|
-
message.currentRetry++;
|
|
119
|
-
this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms`);
|
|
120
|
-
setTimeout(() => {
|
|
121
|
-
this.retryMessage(message, rawMessage, channel);
|
|
122
|
-
}, message.retryInterval);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
await this.updateStatusInDatabase('failed', message, error.message, '');
|
|
126
|
-
this.logger.error(`Message failed after ${message.retryCount} attempts: ${error.message}`);
|
|
127
|
-
channel.ack(rawMessage);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}, {});
|
|
96
|
+
this.logger.error(`Failed to connect to RabbitMQ for queue ${queueName}: ${err.message}`, err.stack);
|
|
97
|
+
this.triggerReconnect(queueName, 'initial connection failure');
|
|
98
|
+
}
|
|
133
99
|
this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${this.url}`);
|
|
134
100
|
}
|
|
135
101
|
}
|
|
136
|
-
async
|
|
137
|
-
await this.
|
|
138
|
-
|
|
102
|
+
async connectAndConsume(queueName) {
|
|
103
|
+
await this.cleanup();
|
|
104
|
+
let connection;
|
|
105
|
+
try {
|
|
106
|
+
connection = await this.establishConnection();
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.logger.error(`Failed to connect to RabbitMQ for queue ${queueName}: ${err.message}`, err.stack);
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
this.connection = connection;
|
|
113
|
+
connection.on('error', (err) => {
|
|
114
|
+
if (connection !== this.connection)
|
|
115
|
+
return;
|
|
116
|
+
this.logger.error(`RabbitMqSubscriber connection error for queue ${queueName}: ${err.message}`);
|
|
117
|
+
});
|
|
118
|
+
connection.on('close', () => {
|
|
119
|
+
if (connection !== this.connection)
|
|
120
|
+
return;
|
|
121
|
+
this.logger.warn(`RabbitMqSubscriber connection closed for queue ${queueName}`);
|
|
122
|
+
this.triggerReconnect(queueName, 'connection closed');
|
|
123
|
+
});
|
|
124
|
+
const channel = await connection.createChannel();
|
|
125
|
+
this.channel = channel;
|
|
126
|
+
channel.on('error', (err) => {
|
|
127
|
+
if (channel !== this.channel)
|
|
128
|
+
return;
|
|
129
|
+
this.logger.error(`RabbitMqSubscriber channel error for queue ${queueName}: ${err.message}`);
|
|
130
|
+
});
|
|
131
|
+
channel.on('close', () => {
|
|
132
|
+
if (channel !== this.channel)
|
|
133
|
+
return;
|
|
134
|
+
this.logger.warn(`RabbitMqSubscriber channel closed for queue ${queueName}`);
|
|
135
|
+
this.triggerReconnect(queueName, 'channel closed');
|
|
136
|
+
});
|
|
137
|
+
await channel.prefetch(1);
|
|
138
|
+
const exchangeName = `${queueName}.exchange`;
|
|
139
|
+
const routingKey = `${queueName}.routing-key`;
|
|
140
|
+
const retryQueue = `${queueName}.retry`;
|
|
141
|
+
const failedQueue = `${queueName}.failed`;
|
|
142
|
+
await channel.assertExchange(exchangeName, 'direct', {});
|
|
143
|
+
await channel.assertQueue(queueName, {});
|
|
144
|
+
await channel.bindQueue(queueName, exchangeName, routingKey);
|
|
145
|
+
await channel.assertQueue(retryQueue, {
|
|
146
|
+
arguments: {
|
|
147
|
+
'x-dead-letter-exchange': exchangeName,
|
|
148
|
+
'x-dead-letter-routing-key': routingKey,
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
await channel.assertQueue(failedQueue, {});
|
|
152
|
+
const consumeResult = await channel.consume(queueName, async (rawMessage) => {
|
|
153
|
+
if (!rawMessage) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const messageContentString = rawMessage.content.toString();
|
|
157
|
+
let message = null;
|
|
158
|
+
try {
|
|
159
|
+
message = JSON.parse(messageContentString);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.logger.error(`Invalid JSON message on queue ${queueName}: ${error.message}`);
|
|
163
|
+
await this.publishToFailedQueue(queueName, rawMessage.content, channel, error);
|
|
164
|
+
channel.ack(rawMessage);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!message.retryCount)
|
|
168
|
+
message.retryCount = 0;
|
|
169
|
+
if (!message.retryInterval)
|
|
170
|
+
message.retryInterval = 1000;
|
|
171
|
+
if (!message.currentRetry)
|
|
172
|
+
message.currentRetry = 0;
|
|
173
|
+
try {
|
|
174
|
+
await this.processMessage(message, rawMessage, channel);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
await this.handleProcessingError(message, rawMessage, channel, error, queueName);
|
|
178
|
+
}
|
|
179
|
+
}, { noAck: false });
|
|
180
|
+
this.consumerTag = consumeResult.consumerTag;
|
|
181
|
+
}
|
|
182
|
+
async handleProcessingError(message, rawMessage, channel, error, queueName) {
|
|
183
|
+
const errorMessage = error?.message || String(error);
|
|
184
|
+
this.logger.error(`Error processing message on queue ${queueName}: ${errorMessage}`);
|
|
185
|
+
if (message.currentRetry < message.retryCount) {
|
|
186
|
+
await this.updateStatusInDatabase('retrying', message);
|
|
187
|
+
message.currentRetry++;
|
|
188
|
+
const retryQueue = `${queueName}.retry`;
|
|
189
|
+
const payload = Buffer.from(JSON.stringify(message));
|
|
190
|
+
channel.sendToQueue(retryQueue, payload, {
|
|
191
|
+
expiration: String(message.retryInterval || 1000),
|
|
192
|
+
headers: {
|
|
193
|
+
'x-error': errorMessage,
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
channel.ack(rawMessage);
|
|
197
|
+
this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms on queue ${queueName}`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
await this.updateStatusInDatabase('failed', message, errorMessage, '');
|
|
139
201
|
channel.ack(rawMessage);
|
|
140
|
-
await this.
|
|
202
|
+
await this.publishToFailedQueue(queueName, Buffer.from(JSON.stringify(message)), channel, error);
|
|
203
|
+
this.logger.error(`Message failed after ${message.retryCount} attempts on queue ${queueName}: ${errorMessage}`);
|
|
141
204
|
}
|
|
142
|
-
async
|
|
205
|
+
async publishToFailedQueue(queueName, payload, channel, error) {
|
|
206
|
+
const failedQueue = `${queueName}.failed`;
|
|
207
|
+
const body = Buffer.isBuffer(payload) ? payload : Buffer.from(payload);
|
|
208
|
+
const errorMessage = error?.message || String(error || '');
|
|
143
209
|
try {
|
|
144
|
-
|
|
210
|
+
channel.sendToQueue(failedQueue, body, errorMessage ? {
|
|
211
|
+
headers: { 'x-error': errorMessage }
|
|
212
|
+
} : undefined);
|
|
145
213
|
}
|
|
146
|
-
catch (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
214
|
+
catch (err) {
|
|
215
|
+
this.logger.error(`Failed to publish to failed queue ${failedQueue}: ${err.message}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
triggerReconnect(queueName, reason) {
|
|
219
|
+
if (this.stopping)
|
|
220
|
+
return;
|
|
221
|
+
if (this.reconnectPromise)
|
|
222
|
+
return;
|
|
223
|
+
this.reconnectPromise = this.reconnectLoop(queueName, reason)
|
|
224
|
+
.finally(() => {
|
|
225
|
+
this.reconnectPromise = null;
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
async reconnectLoop(queueName, reason) {
|
|
229
|
+
this.logger.warn(`RabbitMqSubscriber reconnecting for queue ${queueName}: ${reason}`);
|
|
230
|
+
while (!this.stopping) {
|
|
231
|
+
try {
|
|
232
|
+
await this.connectAndConsume(queueName);
|
|
233
|
+
this.reconnectAttempt = 0;
|
|
234
|
+
this.logger.log(`RabbitMqSubscriber reconnected for queue ${queueName}`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
this.reconnectAttempt += 1;
|
|
239
|
+
const delay = this.backoff();
|
|
240
|
+
this.logger.warn(`RabbitMqSubscriber reconnect failed for queue ${queueName}; retrying in ${delay}ms`);
|
|
241
|
+
await this.sleep(delay);
|
|
159
242
|
}
|
|
160
243
|
}
|
|
161
244
|
}
|
|
245
|
+
async cleanup() {
|
|
246
|
+
const channel = this.channel;
|
|
247
|
+
const connection = this.connection;
|
|
248
|
+
const consumerTag = this.consumerTag;
|
|
249
|
+
this.channel = null;
|
|
250
|
+
this.connection = null;
|
|
251
|
+
this.consumerTag = null;
|
|
252
|
+
if (channel) {
|
|
253
|
+
try {
|
|
254
|
+
if (consumerTag) {
|
|
255
|
+
await channel.cancel(consumerTag);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (_) {
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
await channel.close();
|
|
262
|
+
}
|
|
263
|
+
catch (_) {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (connection) {
|
|
267
|
+
try {
|
|
268
|
+
await connection.close();
|
|
269
|
+
}
|
|
270
|
+
catch (_) {
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
sleep(ms) {
|
|
275
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
276
|
+
}
|
|
277
|
+
backoff() {
|
|
278
|
+
const baseMs = 1000;
|
|
279
|
+
const maxMs = 30_000;
|
|
280
|
+
const exp = Math.min(maxMs, baseMs * Math.pow(2, this.reconnectAttempt));
|
|
281
|
+
const jitter = Math.floor(Math.random() * (exp * 0.2));
|
|
282
|
+
return Math.min(maxMs, exp + jitter);
|
|
283
|
+
}
|
|
284
|
+
async processMessage(message, rawMessage, channel) {
|
|
285
|
+
await this.updateStatusInDatabase('started', message);
|
|
286
|
+
const result = await this.subscribe(message);
|
|
287
|
+
channel.ack(rawMessage);
|
|
288
|
+
await this.updateStatusInDatabase('succeeded', message, '', result ? JSON.stringify(result, null, 2) : '');
|
|
289
|
+
}
|
|
162
290
|
async updateStatusInDatabase(stage, message, error = '', result = '') {
|
|
163
291
|
try {
|
|
164
292
|
const mqMessage = await this.mqMessageService.repo.findOne({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-subscriber.service.js","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, OnModuleInit } from '@nestjs/common';\nimport * as amqp from 'amqplib';\nimport { QueuesModuleOptions } from \"../../interfaces\";\nimport { QueueMessage, QueueSubscriber } from '../../interfaces/mq';\nimport { MqMessageQueueService } from '../mq-message-queue.service';\nimport { MqMessageService } from '../mq-message.service';\n\n\nexport abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscriber<T> { // TODO This can be made a generic type for better type visibility\n private readonly logger = new Logger(RabbitMqSubscriber.name);\n private readonly url: string;\n private readonly serviceRole: string;\n\n constructor(\n protected readonly mqMessageService: MqMessageService,\n protected readonly mqMessageQueueService: MqMessageQueueService,\n ) {\n this.url = process.env.QUEUES_RABBIT_MQ_URL;\n this.serviceRole = process.env.QUEUES_SERVICE_ROLE;\n if (!this.url) {\n this.logger.debug('RabbitMqPublisher url is not defined in the environment variables');\n }\n if (!this.serviceRole) {\n this.logger.debug('Queue service Role is not defined in the environment variables');\n }\n // this.logger.debug(`RabbitMqSubscriber instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n\n abstract subscribe(message: QueueMessage<T>);\n\n abstract options(): QueuesModuleOptions;\n\n async establishConnection(): Promise<amqp.Connection> {\n\n const url = new URL(this.url);\n\n // this.logger.debug(`user: ${url.username}`);\n // // just for local debug, don’t log in prod\n // this.logger.debug(`pass: ${url.password}`);\n // this.logger.debug(`path (vhost): ${url.pathname}`);\n\n const connection = await amqp.connect({\n protocol: url.protocol.replace(':', ''),\n hostname: url.hostname,\n port: parseInt(url.port),\n username: url.username,\n password: decodeURIComponent(url.password),\n frameMax: 131072,\n });\n\n return connection\n }\n\n async onModuleInit(): Promise<void> {\n // Not using SettingService here as that will necessitate all implementors of RabbitMqSubscriber to also inject SettingService which is not ideal. \n // Instead we directly read the environment variables here.\n const defaultBroker = process.env.QUEUES_DEFAULT_BROKER || 'rabbitmq';\n const solidCliRunning = process.env.SOLID_CLI_RUNNING || \"false\";\n const queueNameRegex = (process.env.QUEUES_QUEUE_NAME_REGEX_TO_ENABLE || '').trim();\n\n // we will start subscriber only if the current service role is subscriber. \n if (this.url && ['both', 'subscriber'].includes(this.serviceRole) && solidCliRunning === \"false\" && defaultBroker === 'rabbitmq') {\n const options = this.options();\n const queueName = options.queueName;\n\n if (queueNameRegex && queueNameRegex !== \"all\") {\n try {\n const regex = new RegExp(queueNameRegex);\n if (!regex.test(queueName)) {\n this.logger.log(`RabbitMqSubscriber for queue ${queueName} is disabled because it does not match QUEUES_QUEUE_NAME_REGEX_TO_ENABLE=${queueNameRegex}`);\n return;\n }\n } catch (error) {\n this.logger.error(`Invalid QUEUES_QUEUE_NAME_REGEX_TO_ENABLE regex \"${queueNameRegex}\". Subscriber for queue ${queueName} will not start.`);\n return;\n }\n }\n\n // this.logger.debug(`RabbitMqSubscriber instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);\n // const connection = await amqp.connect(this.url);\n\n let connection;\n try {\n connection = await this.establishConnection();\n // this.logger.debug(`RabbitMqSubscriber connection established: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n catch (err) {\n this.logger.error(`Failed to connect to RabbitMQ: ${(err as Error).message}`, (err as Error).stack);\n throw err;\n }\n\n const channel = await connection.createChannel();\n // this.logger.debug(`RabbitMqSubscriber channel created: ${JSON.stringify(this.options())} and url: ${url}`);\n\n const exchangeName = `${queueName}.exchange`;\n const routingKey = `${queueName}.routing-key`;\n\n await channel.assertExchange(exchangeName, 'direct', {});\n // this.logger.debug(`RabbitMqSubscriber channel asserted: ${JSON.stringify(this.options())} and url: ${url}`);\n\n const queue = await channel.assertQueue(queueName, {});\n // this.logger.debug(`RabbitMqSubscriber queue asserted: ${JSON.stringify(this.options())} and url: ${url}`);\n\n await channel.bindQueue(queue.queue, exchangeName, routingKey);\n // this.logger.debug(`RabbitMqSubscriber queue bound: ${JSON.stringify(this.options())} and url: ${url}`);\n\n // Consume messages from the queue\n channel.consume(\n queue.queue,\n async (rawMessage) => {\n if (rawMessage) {\n const messageContentString = rawMessage.content.toString();\n // this.logger.debug(`RabbitMqSubscriber Received raw message: ${messageContentString}`);\n\n let message: QueueMessage<T> = null;\n\n try {\n message = JSON.parse(messageContentString) as QueueMessage<T>;\n\n // this is the first time we are receiving the message so we set the currentRetry to 0\n if (!message.retryCount) message.retryCount = 0;\n if (!message.retryInterval) message.retryInterval = 1000;\n if (!message.currentRetry) message.currentRetry = 0;\n\n await this.processMessage(message, rawMessage, channel);\n }\n catch (error) {\n this.logger.error(`Error processing message: ${error.message}`);\n\n // if an error occurs then if retryCount is set we start retrying. \n if (message) {\n if (message.currentRetry < message.retryCount) {\n await this.updateStatusInDatabase('retrying', message);\n\n message.currentRetry++;\n this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms`);\n setTimeout(() => {\n this.retryMessage(message, rawMessage, channel);\n }, message.retryInterval);\n } else {\n await this.updateStatusInDatabase('failed', message, error.message, '');\n\n this.logger.error(`Message failed after ${message.retryCount} attempts: ${error.message}`);\n channel.ack(rawMessage); // Discard the message after max retries\n }\n }\n\n }\n }\n },\n // { noAck: true },\n {},\n );\n\n this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n }\n\n /**\n * Abstract method for message processing logic.\n */\n protected async processMessage(message: QueueMessage<T>, rawMessage, channel): Promise<void> {\n await this.updateStatusInDatabase('started', message);\n\n // Capture the results of handling the task.\n const result = await this.subscribe(message);\n\n // Ack the message. \n channel.ack(rawMessage);\n\n // TODO: Update the database to indicate that the task is finished.\n await this.updateStatusInDatabase('succeeded', message, '', result ? JSON.stringify(result, null, 2) : '');\n\n }\n\n /**\n * Retry the message by invoking the processing logic again.\n */\n private async retryMessage(message: QueueMessage<T>, rawMessage, channel) {\n try {\n await this.processMessage(message, rawMessage, channel);\n } catch (error) {\n if (message.currentRetry < message.retryCount) {\n await this.updateStatusInDatabase('retrying', message);\n\n message.currentRetry++;\n this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms: ${error.message}`);\n setTimeout(() => {\n this.retryMessage(message, rawMessage, channel);\n }, message.retryInterval);\n } else {\n\n this.logger.error(`Message failed after ${message.retryCount} attempts: ${error.message}`);\n\n // Discard the message after max retries\n channel.ack(rawMessage);\n\n // TODO: Store the error in the database and update the status accordingly.\n await this.updateStatusInDatabase('failed', message, error.message, '');\n\n }\n }\n }\n\n private async updateStatusInDatabase(stage: string, message: QueueMessage<T>, error: string = '', result: string = '') {\n\n // TODO: make an entry in the relevant database table, generate a unique id earlier.\n try {\n // 1. resolve the queue first\n const mqMessage = await this.mqMessageService.repo.findOne({\n where: {\n messageId: message.messageId,\n }\n });\n\n if (mqMessage) {\n const updatedFields = {\n stage: stage\n };\n if (stage === 'failed' || stage === 'succeeded') {\n updatedFields['finishedAt'] = new Date();\n updatedFields['elapsedMillis'] = updatedFields['finishedAt'].getTime() - mqMessage.startedAt.getTime();\n }\n if (stage === 'succeeded') {\n updatedFields['output'] = result;\n }\n if (stage === 'failed') {\n updatedFields['error'] = error;\n }\n await this.mqMessageService.repo.update(mqMessage.id, updatedFields);\n }\n }\n catch (error) {\n this.logger.error(error.message, error.stack);\n }\n\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rabbitmq-subscriber.service.js","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, OnModuleInit } from '@nestjs/common';\nimport * as amqp from 'amqplib';\nimport { QueuesModuleOptions } from \"../../interfaces\";\nimport { QueueMessage, QueueSubscriber } from '../../interfaces/mq';\nimport { MqMessageQueueService } from '../mq-message-queue.service';\nimport { MqMessageService } from '../mq-message.service';\n\n\nexport abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscriber<T> { // TODO This can be made a generic type for better type visibility\n private readonly logger = new Logger(RabbitMqSubscriber.name);\n private readonly url: string;\n private readonly serviceRole: string;\n private connection: amqp.Connection | null = null;\n private channel: amqp.Channel | null = null;\n private consumerTag: string | null = null;\n private reconnectPromise: Promise<void> | null = null;\n private reconnectAttempt = 0;\n private stopping = false;\n\n constructor(protected readonly mqMessageService: MqMessageService, protected readonly mqMessageQueueService: MqMessageQueueService) {\n this.url = process.env.QUEUES_RABBIT_MQ_URL;\n this.serviceRole = process.env.QUEUES_SERVICE_ROLE;\n if (!this.url) {\n this.logger.debug('RabbitMqPublisher url is not defined in the environment variables');\n }\n if (!this.serviceRole) {\n this.logger.debug('Queue service Role is not defined in the environment variables');\n }\n // this.logger.debug(`RabbitMqSubscriber instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n\n abstract subscribe(message: QueueMessage<T>);\n\n abstract options(): QueuesModuleOptions;\n\n async establishConnection(): Promise<amqp.Connection> {\n\n const url = new URL(this.url);\n\n // this.logger.debug(`user: ${url.username}`);\n // // just for local debug, don’t log in prod\n // this.logger.debug(`pass: ${url.password}`);\n // this.logger.debug(`path (vhost): ${url.pathname}`);\n\n const connection = await amqp.connect({\n protocol: url.protocol.replace(':', ''),\n hostname: url.hostname,\n port: parseInt(url.port),\n username: url.username,\n password: decodeURIComponent(url.password),\n frameMax: 131072,\n heartbeat: 30,\n });\n\n return connection\n }\n\n async onModuleInit(): Promise<void> {\n // Not using SettingService here as that will necessitate all implementors of RabbitMqSubscriber to also inject SettingService which is not ideal. \n // Instead we directly read the environment variables here.\n const defaultBroker = process.env.QUEUES_DEFAULT_BROKER || 'rabbitmq';\n const solidCliRunning = process.env.SOLID_CLI_RUNNING || \"false\";\n const queueNameRegex = (process.env.QUEUES_QUEUE_NAME_REGEX_TO_ENABLE || '').trim();\n\n // we will start subscriber only if the current service role is subscriber. \n if (this.url && ['both', 'subscriber'].includes(this.serviceRole) && solidCliRunning === \"false\" && defaultBroker === 'rabbitmq') {\n const options = this.options();\n const queueName = options.queueName;\n\n if (queueNameRegex && queueNameRegex !== \"all\") {\n try {\n const regex = new RegExp(queueNameRegex);\n if (!regex.test(queueName)) {\n this.logger.log(`RabbitMqSubscriber for queue ${queueName} is disabled because it does not match QUEUES_QUEUE_NAME_REGEX_TO_ENABLE=${queueNameRegex}`);\n return;\n }\n } catch (error) {\n this.logger.error(`Invalid QUEUES_QUEUE_NAME_REGEX_TO_ENABLE regex \"${queueNameRegex}\". Subscriber for queue ${queueName} will not start.`);\n return;\n }\n }\n\n try {\n await this.connectAndConsume(queueName);\n } catch (err) {\n this.logger.error(`Failed to connect to RabbitMQ for queue ${queueName}: ${(err as Error).message}`, (err as Error).stack);\n this.triggerReconnect(queueName, 'initial connection failure');\n }\n\n this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n }\n\n private async connectAndConsume(queueName: string): Promise<void> {\n await this.cleanup();\n\n let connection: amqp.Connection;\n try {\n connection = await this.establishConnection();\n } catch (err) {\n this.logger.error(`Failed to connect to RabbitMQ for queue ${queueName}: ${(err as Error).message}`, (err as Error).stack);\n throw err;\n }\n\n this.connection = connection;\n\n connection.on('error', (err) => {\n if (connection !== this.connection) return;\n this.logger.error(`RabbitMqSubscriber connection error for queue ${queueName}: ${(err as Error).message}`);\n });\n\n connection.on('close', () => {\n if (connection !== this.connection) return;\n this.logger.warn(`RabbitMqSubscriber connection closed for queue ${queueName}`);\n this.triggerReconnect(queueName, 'connection closed');\n });\n\n const channel = await connection.createChannel();\n this.channel = channel;\n\n channel.on('error', (err) => {\n if (channel !== this.channel) return;\n this.logger.error(`RabbitMqSubscriber channel error for queue ${queueName}: ${(err as Error).message}`);\n });\n\n channel.on('close', () => {\n if (channel !== this.channel) return;\n this.logger.warn(`RabbitMqSubscriber channel closed for queue ${queueName}`);\n this.triggerReconnect(queueName, 'channel closed');\n });\n\n // Process one message at a time per consumer to avoid parallel work on the same subscriber instance.\n await channel.prefetch(1);\n\n // Use a direct exchange with a stable routing key so retry DLX can route back to the main queue.\n const exchangeName = `${queueName}.exchange`;\n const routingKey = `${queueName}.routing-key`;\n const retryQueue = `${queueName}.retry`;\n const failedQueue = `${queueName}.failed`;\n\n await channel.assertExchange(exchangeName, 'direct', {});\n await channel.assertQueue(queueName, {});\n await channel.bindQueue(queueName, exchangeName, routingKey);\n\n // Retry queue uses DLX to route expired messages back to the main exchange/routing key.\n await channel.assertQueue(retryQueue, {\n arguments: {\n 'x-dead-letter-exchange': exchangeName,\n 'x-dead-letter-routing-key': routingKey,\n }\n });\n\n await channel.assertQueue(failedQueue, {});\n\n const consumeResult = await channel.consume(\n queueName,\n async (rawMessage) => {\n if (!rawMessage) {\n return;\n }\n\n const messageContentString = rawMessage.content.toString();\n let message: QueueMessage<T> = null;\n\n try {\n message = JSON.parse(messageContentString) as QueueMessage<T>;\n } catch (error) {\n this.logger.error(`Invalid JSON message on queue ${queueName}: ${(error as Error).message}`);\n await this.publishToFailedQueue(queueName, rawMessage.content, channel, error);\n channel.ack(rawMessage);\n return;\n }\n\n if (!message.retryCount) message.retryCount = 0;\n if (!message.retryInterval) message.retryInterval = 1000;\n if (!message.currentRetry) message.currentRetry = 0;\n\n try {\n await this.processMessage(message, rawMessage, channel);\n } catch (error) {\n await this.handleProcessingError(message, rawMessage, channel, error, queueName);\n }\n },\n // Explicit ack enables reliable processing and retry routing.\n { noAck: false },\n );\n\n this.consumerTag = consumeResult.consumerTag;\n }\n\n // Retry flow: update DB -> increment retry -> send to retry queue with per-message expiration -> ack original.\n private async handleProcessingError(message: QueueMessage<T>, rawMessage: amqp.ConsumeMessage, channel: amqp.Channel, error: any, queueName: string): Promise<void> {\n const errorMessage = (error as Error)?.message || String(error);\n this.logger.error(`Error processing message on queue ${queueName}: ${errorMessage}`);\n\n if (message.currentRetry < message.retryCount) {\n await this.updateStatusInDatabase('retrying', message);\n\n message.currentRetry++;\n const retryQueue = `${queueName}.retry`;\n const payload = Buffer.from(JSON.stringify(message));\n\n // Per-message expiration keeps the message in the retry queue until TTL, then DLX routes it back.\n channel.sendToQueue(retryQueue, payload, {\n expiration: String(message.retryInterval || 1000),\n headers: {\n 'x-error': errorMessage,\n }\n });\n\n channel.ack(rawMessage);\n this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms on queue ${queueName}`);\n return;\n }\n\n await this.updateStatusInDatabase('failed', message, errorMessage, '');\n channel.ack(rawMessage);\n await this.publishToFailedQueue(queueName, Buffer.from(JSON.stringify(message)), channel, error);\n this.logger.error(`Message failed after ${message.retryCount} attempts on queue ${queueName}: ${errorMessage}`);\n }\n\n private async publishToFailedQueue(queueName: string, payload: Buffer | string, channel: amqp.Channel, error?: any): Promise<void> {\n const failedQueue = `${queueName}.failed`;\n const body = Buffer.isBuffer(payload) ? payload : Buffer.from(payload);\n const errorMessage = (error as Error)?.message || String(error || '');\n\n try {\n channel.sendToQueue(failedQueue, body, errorMessage ? {\n headers: { 'x-error': errorMessage }\n } : undefined);\n } catch (err) {\n this.logger.error(`Failed to publish to failed queue ${failedQueue}: ${(err as Error).message}`);\n }\n }\n\n private triggerReconnect(queueName: string, reason: string) {\n if (this.stopping) return;\n if (this.reconnectPromise) return;\n\n this.reconnectPromise = this.reconnectLoop(queueName, reason)\n .finally(() => {\n this.reconnectPromise = null;\n });\n }\n\n // Reconnect with backoff to avoid hammering the broker during outages.\n private async reconnectLoop(queueName: string, reason: string): Promise<void> {\n this.logger.warn(`RabbitMqSubscriber reconnecting for queue ${queueName}: ${reason}`);\n\n while (!this.stopping) {\n try {\n await this.connectAndConsume(queueName);\n this.reconnectAttempt = 0;\n this.logger.log(`RabbitMqSubscriber reconnected for queue ${queueName}`);\n return;\n } catch (err) {\n this.reconnectAttempt += 1;\n const delay = this.backoff();\n this.logger.warn(`RabbitMqSubscriber reconnect failed for queue ${queueName}; retrying in ${delay}ms`);\n await this.sleep(delay);\n }\n }\n }\n\n private async cleanup(): Promise<void> {\n const channel = this.channel;\n const connection = this.connection;\n const consumerTag = this.consumerTag;\n\n this.channel = null;\n this.connection = null;\n this.consumerTag = null;\n\n if (channel) {\n try {\n if (consumerTag) {\n await channel.cancel(consumerTag);\n }\n } catch (_) {\n // ignore\n }\n\n try {\n await channel.close();\n } catch (_) {\n // ignore\n }\n }\n\n if (connection) {\n try {\n await connection.close();\n } catch (_) {\n // ignore\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n // Exponential backoff with jitter, capped to 30s.\n private backoff(): number {\n const baseMs = 1000;\n const maxMs = 30_000;\n const exp = Math.min(maxMs, baseMs * Math.pow(2, this.reconnectAttempt));\n const jitter = Math.floor(Math.random() * (exp * 0.2));\n return Math.min(maxMs, exp + jitter);\n }\n\n /**\n * Abstract method for message processing logic.\n */\n protected async processMessage(message: QueueMessage<T>, rawMessage, channel): Promise<void> {\n await this.updateStatusInDatabase('started', message);\n\n // Capture the results of handling the task.\n const result = await this.subscribe(message);\n\n // Ack the message. \n channel.ack(rawMessage);\n\n // Persist success output and timing.\n await this.updateStatusInDatabase('succeeded', message, '', result ? JSON.stringify(result, null, 2) : '');\n\n }\n\n private async updateStatusInDatabase(stage: string, message: QueueMessage<T>, error: string = '', result: string = '') {\n\n // Update the existing message record by messageId; creation happens upstream.\n try {\n // 1. resolve the queue first\n const mqMessage = await this.mqMessageService.repo.findOne({\n where: {\n messageId: message.messageId,\n }\n });\n\n if (mqMessage) {\n const updatedFields = {\n stage: stage\n };\n if (stage === 'failed' || stage === 'succeeded') {\n updatedFields['finishedAt'] = new Date();\n updatedFields['elapsedMillis'] = updatedFields['finishedAt'].getTime() - mqMessage.startedAt.getTime();\n }\n if (stage === 'succeeded') {\n updatedFields['output'] = result;\n }\n if (stage === 'failed') {\n updatedFields['error'] = error;\n }\n await this.mqMessageService.repo.update(mqMessage.id, updatedFields);\n }\n }\n catch (error) {\n this.logger.error(error.message, error.stack);\n }\n\n }\n\n}\n"]}
|