@solidxai/core 0.1.6-beta.23 → 0.1.6-beta.24
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/bootstrap.helper.js +1 -1
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.js +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.js.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.d.ts +1 -0
- package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.js +6 -1
- package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +1 -0
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +15 -4
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/request-context.service.d.ts +2 -1
- package/dist/services/request-context.service.d.ts.map +1 -1
- package/dist/services/request-context.service.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts +0 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js +3 -13
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/dist-tests/api/authenticate.spec.js +119 -0
- package/dist-tests/api/authenticate.spec.js.map +1 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
- package/dist-tests/api/ping.spec.js +21 -0
- package/dist-tests/api/ping.spec.js.map +1 -0
- package/dist-tests/helpers/auth.js +41 -0
- package/dist-tests/helpers/auth.js.map +1 -0
- package/dist-tests/helpers/env.js +11 -0
- package/dist-tests/helpers/env.js.map +1 -0
- package/package.json +1 -1
- package/src/helpers/bootstrap.helper.ts +1 -1
- package/src/interfaces.ts +1 -0
- package/src/jobs/computed-field-evaluation-queue-options.ts +1 -0
- package/src/services/queues/rabbitmq-publisher.service.ts +8 -2
- package/src/services/queues/rabbitmq-subscriber.service.ts +16 -5
- package/src/services/request-context.service.ts +2 -1
- package/src/subscribers/created-by-updated-by.subscriber.ts +22 -16
- package/.claude/settings.local.json +0 -15
- package/logs_load_testing +0 -49
- package/src/services/1.js +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.helper.js","sourceRoot":"","sources":["../../src/helpers/bootstrap.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { ValidationPipe } from '@nestjs/common';\nimport { NestFactory } from '@nestjs/core';\nimport { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';\nimport { NextFunction, Request, Response } from 'express';\nimport helmet from 'helmet';\nimport qs from 'qs';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';\nimport { CommandFactory } from 'nest-commander';\nimport { WrapResponseInterceptor } from '../interceptors/wrap-response.interceptor';\nimport { buildDefaultCorsOptions } from './cors.helper';\nimport { buildDefaultSecurityHeaderOptions, buildPermissionsPolicyHeader, PermissionsPolicyConfig } from './security.helper';\nimport { parseBooleanEnv } from './environment.helper';\n\n// ---- Shared process handlers ----\n\nfunction registerGlobalProcessHandlers() {\n process.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n });\n\n process.on('uncaughtException', (err) => {\n console.error('Uncaught Exception thrown:', err);\n });\n\n // Suppress pg deprecation warning caused by TypeORM's internal query scheduling\n process.on('warning', (warning) => {\n if (warning.name === 'DeprecationWarning' && (warning.message.includes('client.query()') || warning.message.includes('punycode'))) {\n return;\n }\n console.warn(warning);\n });\n}\n\n// ---- HTTP server bootstrap ----\n\nexport interface SolidSwaggerOptions {\n title?: string;\n description?: string;\n version?: string;\n}\n\nexport interface SolidBootstrapOptions {\n /** Global API prefix. Defaults to 'api'. Set to '' to disable. */\n globalPrefix?: string;\n /** Swagger configuration. Set to false to disable Swagger entirely. */\n swagger?: SolidSwaggerOptions | false;\n /** Permissions-Policy header overrides (merged with defaults). */\n permissionsPolicyOverrides?: Partial<PermissionsPolicyConfig>;\n}\n\n/**\n * Bootstraps a SolidX NestJS HTTP application with sensible defaults:\n * security headers, CORS, Winston logger, ValidationPipe,\n * WrapResponseInterceptor, qs deep query parsing, Swagger, and the\n * pg BIGINT type parser.\n *\n * @example\n * // main.ts\n * bootstrapSolidApp(() => AppModule.forRoot(), {\n * swagger: { title: 'My API', description: 'My API description' },\n * });\n */\nexport async function bootstrapSolidApp(\n appModuleFactory: () => Promise<any>,\n options: SolidBootstrapOptions = {},\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n const { globalPrefix = 'api', swagger = {}, permissionsPolicyOverrides = {} } = options;\n\n const appModule = await appModuleFactory();\n const app = await NestFactory.create(appModule);\n\n const apiEnabled = parseBooleanEnv('API_ENABLED', true);\n\n if (!apiEnabled) {\n await app.init();\n app\n .get(WINSTON_MODULE_NEST_PROVIDER)\n .log('API server disabled via API_ENABLED=false. Skipping HTTP listen.', 'Bootstrap');\n return;\n }\n\n // Health check at root path\n const server = app.getHttpAdapter().getInstance();\n server.get('/', (_req, res) => res.status(200).send('SOLID OK'));\n\n // Security headers\n app.use(helmet(buildDefaultSecurityHeaderOptions()));\n\n // Permissions-Policy header\n app.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader('Permissions-Policy', buildPermissionsPolicyHeader(permissionsPolicyOverrides));\n next();\n });\n\n // Winston logger\n app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));\n\n const port = process.env.PORT || 3000;\n\n if (globalPrefix) {\n app.setGlobalPrefix(globalPrefix);\n }\n\n // qs-based deep query parsing (dot notation, nested objects, arrays)\n app.use((req: Request, _res: Response, next: NextFunction) => {\n if (req.query) {\n req.query = qs.parse(req.url.split('?')[1], {\n allowDots: true,\n depth: 10,\n arrayLimit: 100,\n });\n }\n next();\n });\n\n // Global ValidationPipe\n app.useGlobalPipes(\n new ValidationPipe({\n transform: true,\n transformOptions: { enableImplicitConversion: true },\n }),\n );\n\n // Swagger\n if (swagger !== false) {\n const { title = 'Solid Starters', description = 'Solid Starters API', version = '1.0' } = swagger;\n const swaggerConfig = new DocumentBuilder()\n .setTitle(title)\n .setDescription(description)\n .setVersion(version)\n .setExternalDoc('Postman Collection', '/docs-json')\n .addBearerAuth(\n {\n description: 'Please enter token in following format: Bearer <JWT>',\n name: 'Authorization',\n bearerFormat: 'Bearer',\n scheme: 'Bearer',\n type: 'http',\n in: 'Header',\n },\n 'jwt',\n )\n .build();\n const document = SwaggerModule.createDocument(app, swaggerConfig);\n SwaggerModule.setup('/docs', app, document);\n }\n\n // Global interceptor\n app.useGlobalInterceptors(new WrapResponseInterceptor());\n\n // CORS\n app.enableCors(buildDefaultCorsOptions());\n\n // Fix pg returning BIGINT columns as strings\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const types = require('pg').types;\n types.setTypeParser(types.builtins.INT8, (val: string) => parseInt(val));\n\n await app.listen(port);\n}\n\n// ---- CLI bootstrap ----\n\n/**\n * Bootstraps a SolidX NestJS CLI application using nest-commander.\n * Handles verbose flag stripping, project root validation, and clean process exit.\n *\n * @example\n * // main-cli.ts\n * #!/usr/bin/env node\n * import { bootstrapSolidCli } from '@solidxai/core';\n * import { AppModule } from './app.module';\n *\n * bootstrapSolidCli(() => AppModule.forRoot());\n */\nexport async function bootstrapSolidCli(\n appModuleFactory: () => Promise<any>,\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n process.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Exiting with error status code: ${code}`);\n }\n });\n\n // Validate that cwd is a valid Solid API project\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n if (!existsSync(packageJsonPath)) {\n console.error('Does not seem to be a valid solid-api project.');\n console.error('Exit reason: missing package.json in the current directory.');\n process.exit(1);\n }\n\n // Strip --verbose / -v before nest-commander processes argv\n const showLogs = process.argv.includes('--verbose') || process.argv.includes('-v');\n for (const flag of ['--verbose', '-v']) {\n const idx = process.argv.indexOf(flag);\n if (idx !== -1) process.argv.splice(idx, 1);\n }\n\n const appModule = await appModuleFactory();\n process.env.SOLID_CLI_RUNNING = 'true';\n\n // @ts-ignore\n const app = await CommandFactory.createWithoutRunning(appModule, {\n logger: showLogs ? ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'] : false,\n });\n\n try {\n await CommandFactory.runApplication(app);\n } catch (e) {\n console.error('CLI exited abruptly due to an error:', e);\n process.exit(1);\n }\n\n process.exit(0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bootstrap.helper.js","sourceRoot":"","sources":["../../src/helpers/bootstrap.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { ValidationPipe } from '@nestjs/common';\nimport { NestFactory } from '@nestjs/core';\nimport { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';\nimport { NextFunction, Request, Response } from 'express';\nimport helmet from 'helmet';\nimport qs from 'qs';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';\nimport { CommandFactory } from 'nest-commander';\nimport { WrapResponseInterceptor } from '../interceptors/wrap-response.interceptor';\nimport { buildDefaultCorsOptions } from './cors.helper';\nimport { buildDefaultSecurityHeaderOptions, buildPermissionsPolicyHeader, PermissionsPolicyConfig } from './security.helper';\nimport { parseBooleanEnv } from './environment.helper';\n\n// ---- Shared process handlers ----\n\nfunction registerGlobalProcessHandlers() {\n process.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n });\n\n process.on('uncaughtException', (err) => {\n console.error('Uncaught Exception thrown:', err);\n });\n\n // Suppress pg deprecation warning caused by TypeORM's internal query scheduling\n process.on('warning', (warning) => {\n if (warning.name === 'DeprecationWarning' && (warning.message.includes('client.query()') || warning.message.includes('punycode'))) {\n return;\n }\n console.warn(warning);\n });\n}\n\n// ---- HTTP server bootstrap ----\n\nexport interface SolidSwaggerOptions {\n title?: string;\n description?: string;\n version?: string;\n}\n\nexport interface SolidBootstrapOptions {\n /** Global API prefix. Defaults to 'api'. Set to '' to disable. */\n globalPrefix?: string;\n /** Swagger configuration. Set to false to disable Swagger entirely. */\n swagger?: SolidSwaggerOptions | false;\n /** Permissions-Policy header overrides (merged with defaults). */\n permissionsPolicyOverrides?: Partial<PermissionsPolicyConfig>;\n}\n\n/**\n * Bootstraps a SolidX NestJS HTTP application with sensible defaults:\n * security headers, CORS, Winston logger, ValidationPipe,\n * WrapResponseInterceptor, qs deep query parsing, Swagger, and the\n * pg BIGINT type parser.\n *\n * @example\n * // main.ts\n * bootstrapSolidApp(() => AppModule.forRoot(), {\n * swagger: { title: 'My API', description: 'My API description' },\n * });\n */\nexport async function bootstrapSolidApp(\n appModuleFactory: () => Promise<any>,\n options: SolidBootstrapOptions = {},\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n const { globalPrefix = 'api', swagger = {}, permissionsPolicyOverrides = {} } = options;\n\n const appModule = await appModuleFactory();\n const app = await NestFactory.create(appModule);\n\n const apiEnabled = parseBooleanEnv('API_ENABLED', true);\n\n if (!apiEnabled) {\n await app.init();\n app\n .get(WINSTON_MODULE_NEST_PROVIDER)\n .log('API server disabled via API_ENABLED=false. Skipping HTTP listen.', 'Bootstrap');\n return;\n }\n\n // Health check at root path\n const server = app.getHttpAdapter().getInstance();\n server.get('/', (_req, res) => res.status(200).send('SOLID OK'));\n\n // Security headers\n app.use(helmet(buildDefaultSecurityHeaderOptions()));\n\n // Permissions-Policy header\n app.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader('Permissions-Policy', buildPermissionsPolicyHeader(permissionsPolicyOverrides));\n next();\n });\n\n // Winston logger\n app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));\n\n const port = process.env.PORT || 3000;\n\n if (globalPrefix) {\n app.setGlobalPrefix(globalPrefix);\n }\n\n // qs-based deep query parsing (dot notation, nested objects, arrays)\n app.use((req: Request, _res: Response, next: NextFunction) => {\n if (req.query) {\n req.query = qs.parse(req.url.split('?')[1], {\n allowDots: true,\n depth: 20,\n arrayLimit: 100,\n });\n }\n next();\n });\n\n // Global ValidationPipe\n app.useGlobalPipes(\n new ValidationPipe({\n transform: true,\n transformOptions: { enableImplicitConversion: true },\n }),\n );\n\n // Swagger\n if (swagger !== false) {\n const { title = 'Solid Starters', description = 'Solid Starters API', version = '1.0' } = swagger;\n const swaggerConfig = new DocumentBuilder()\n .setTitle(title)\n .setDescription(description)\n .setVersion(version)\n .setExternalDoc('Postman Collection', '/docs-json')\n .addBearerAuth(\n {\n description: 'Please enter token in following format: Bearer <JWT>',\n name: 'Authorization',\n bearerFormat: 'Bearer',\n scheme: 'Bearer',\n type: 'http',\n in: 'Header',\n },\n 'jwt',\n )\n .build();\n const document = SwaggerModule.createDocument(app, swaggerConfig);\n SwaggerModule.setup('/docs', app, document);\n }\n\n // Global interceptor\n app.useGlobalInterceptors(new WrapResponseInterceptor());\n\n // CORS\n app.enableCors(buildDefaultCorsOptions());\n\n // Fix pg returning BIGINT columns as strings\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const types = require('pg').types;\n types.setTypeParser(types.builtins.INT8, (val: string) => parseInt(val));\n\n await app.listen(port);\n}\n\n// ---- CLI bootstrap ----\n\n/**\n * Bootstraps a SolidX NestJS CLI application using nest-commander.\n * Handles verbose flag stripping, project root validation, and clean process exit.\n *\n * @example\n * // main-cli.ts\n * #!/usr/bin/env node\n * import { bootstrapSolidCli } from '@solidxai/core';\n * import { AppModule } from './app.module';\n *\n * bootstrapSolidCli(() => AppModule.forRoot());\n */\nexport async function bootstrapSolidCli(\n appModuleFactory: () => Promise<any>,\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n process.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Exiting with error status code: ${code}`);\n }\n });\n\n // Validate that cwd is a valid Solid API project\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n if (!existsSync(packageJsonPath)) {\n console.error('Does not seem to be a valid solid-api project.');\n console.error('Exit reason: missing package.json in the current directory.');\n process.exit(1);\n }\n\n // Strip --verbose / -v before nest-commander processes argv\n const showLogs = process.argv.includes('--verbose') || process.argv.includes('-v');\n for (const flag of ['--verbose', '-v']) {\n const idx = process.argv.indexOf(flag);\n if (idx !== -1) process.argv.splice(idx, 1);\n }\n\n const appModule = await appModuleFactory();\n process.env.SOLID_CLI_RUNNING = 'true';\n\n // @ts-ignore\n const app = await CommandFactory.createWithoutRunning(appModule, {\n logger: showLogs ? ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'] : false,\n });\n\n try {\n await CommandFactory.runApplication(app);\n } catch (e) {\n console.error('CLI exited abruptly due to an error:', e);\n process.exit(1);\n }\n\n process.exit(0);\n}\n"]}
|
package/dist/interfaces.d.ts
CHANGED
package/dist/interfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"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"}
|
package/dist/interfaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";;;AA4DA,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,wCAAwB,CAAA;IACxB,6DAA6C,CAAA;IAC7C,6DAA6C,CAAA;IAC7C,8CAA8B,CAAA;AAChC,CAAC,EALW,YAAY,4BAAZ,YAAY,QAKvB;AA0HD,IAAY,SAEX;AAFD,WAAY,SAAS;IACnB,gDAAmC,CAAA;AACrC,CAAC,EAFW,SAAS,yBAAT,SAAS,QAEpB;AAED,MAAa,YAAY;IACvB,YACS,IAAS,EACT,OAAU;QADV,SAAI,GAAJ,IAAI,CAAK;QACT,YAAO,GAAP,OAAO,CAAG;IACf,CAAC;CACN;AALD,oCAKC;AAmED,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,mCAAqB,CAAA;IACrB,mCAAqB,CAAA;AACvB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB","sourcesContent":["import { CreateEmailTemplateDto } from 'src/dtos/create-email-template.dto';\nimport { CreateSmsTemplateDto } from 'src/dtos/create-sms-template.dto';\nimport { SignUpDto } from 'src/dtos/sign-up.dto';\nimport { Readable } from 'stream';\nimport { CreateMediaStorageProviderMetadataDto } from './dtos/create-media-storage-provider-metadata.dto';\nimport { DatasourceType } from './dtos/create-model-metadata.dto';\nimport { CreateModuleMetadataDto } from './dtos/create-module-metadata.dto';\nimport { CreateRoleMetadataDto } from './dtos/create-role-metadata.dto';\nimport { CreateSecurityRuleDto } from './dtos/create-security-rule.dto';\nimport { FieldMetadata } from './entities/field-metadata.entity';\nimport { Media } from './entities/media.entity';\nimport { DashboardQuestion } from './entities/dashboard-question.entity';\nimport { ComputedFieldMetadata } from './helpers/solid-registry';\nimport { SqlExpression } from './services/question-data-providers/chartjs-sql-data-provider.service';\nimport { CreateDashboardDto } from './dtos/create-dashboard.dto';\nimport { AiInteraction } from './entities/ai-interaction.entity';\nimport { ActiveUserData } from './interfaces/active-user-data.interface';\nimport { SecurityRuleConfig } from './dtos/security-rule-config.dto';\nimport { SecurityRule } from './entities/security-rule.entity';\n\nexport interface FieldCrudManager {\n // fieldMetadata: FieldMetadata;\n // entityManager?: EntityManager;\n // createDto: any;\n // files : Array<Express.Multer.File>;\n validate(\n dto: any,\n files: Array<Express.Multer.File>,\n ): ValidationError[] | Promise<ValidationError[]>;\n transformForCreate(dto: any, ctxt?: any): any | Promise<any>;\n}\n\nexport interface ValidationError {\n field: string;\n error: string;\n}\n\n// export interface MediaStorage\nexport interface MediaStorageProvider<T> {\n store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;\n retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n // delete(file: string): Promise<void>;\n}\n\nexport interface ModuleMetadataConfiguration {\n moduleMetadata?: CreateModuleMetadataDto,\n roles?: CreateRoleMetadataDto[],\n users?: SignUpDto[],\n actions?: any[],\n menus?: any[],\n views?: any[],\n emailTemplates?: CreateEmailTemplateDto[],\n smsTemplates?: CreateSmsTemplateDto[],\n mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]\n securityRules?: CreateSecurityRuleDto[],\n dashboards?: CreateDashboardDto[],\n}\n\nexport enum SettingLevel {\n SystemEnv = 'system-env',\n SystemAdminReadonly = 'system-admin-readonly',\n SystemAdminEditable = 'system-admin-editable',\n InternalUser = \"internal-user\"\n}\n\nexport interface SettingDefinition<T = any> {\n moduleName: string;\n key: string;\n value: T;\n level: SettingLevel;\n}\n\n// solid-core/settings/settings-provider.interface.ts\nexport interface ISettingsProvider {\n getSettings(): SettingDefinition[];\n}\n\nexport interface CodeGenerationOptions {\n moduleId?: number;\n moduleUserKey?: string;\n modelId?: number;\n modelUserKey?: string;\n fieldIdsForRemoval?: number[];\n fieldNamesForRemoval?: string[];\n dryRun?: boolean;\n fieldIdsForRefresh?: number[];\n fieldNamesForRefresh?: string[];\n}\n\nexport interface TriggerMcpClientOptions {\n aiInteractionId: number;\n moduleName: string;\n}\n\nexport interface McpResponse {\n success: boolean;\n request: string;\n response: string;\n model?: string;\n tools_invoked?: string[];\n tool_calls?: any[];\n duration_ms?: number;\n errors?: string[];\n error_trace?: string[];\n content_type?: string;\n}\n\nexport interface ISelectionProviderContext {\n limit: number;\n offset: number;\n formValues: Record<string, any>;\n //Attribute to control the validation on creating the record\n validateOnSave?: boolean;\n // query: string;\n}\n\nexport interface ISelectionProviderValues {\n label: string;\n value: string;\n}\n\nexport interface ISelectionProvider<T extends ISelectionProviderContext> {\n help(): string;\n\n name(): string;\n\n value(optionValue: string, ctxt: T): Promise<ISelectionProviderValues | any>;\n\n values(query: any, ctxt: T): Promise<readonly ISelectionProviderValues[]>;\n}\n\nexport interface IDashboardVariableSelectionProvider<T extends ISelectionProviderContext> extends ISelectionProvider<T> {\n}\n\nexport interface IMcpToolResponseHandler {\n apply(aiInteraction: AiInteraction);\n}\n\nexport interface QuestionSqlDataProviderContext {\n // questionSqlDatasetConfig: QuestionSqlDatasetConfig;\n // questionId: number;\n // question: Question;\n expressions?: SqlExpression[]\n}\nexport interface IDashboardQuestionDataProvider<TContext, TData> {\n help(): string;\n\n name(): string;\n\n getData(question: DashboardQuestion, ctxt?: TContext): Promise<TData[] | TData>;\n}\n\n/**\n * @deprecated Use `IEntityComputedFieldProvider` instead.\n */\nexport interface IComputedFieldProvider<T> {\n help(): string;\n\n name(): string;\n\n valueType(): string;\n\n computeValue(dto: any, ctxt: T): Promise<string | number>; // FIXME : Improve the types to make it more specific using generics\n}\n\nexport interface IEntityComputedFieldProvider {\n help(): string;\n\n name(): string;\n}\n\nexport interface IEntityPreComputeFieldProvider<TTriggerEntity, TContext, TValue = void> extends IEntityComputedFieldProvider {\n preComputeValue(triggerEntity: TTriggerEntity, computedFieldMetadata: ComputedFieldMetadata<TContext>): Promise<TValue>;\n}\n\nexport interface IEntityPostComputeFieldProvider<TTriggerEntity, TContext> extends IEntityComputedFieldProvider {\n postComputeAndSaveValue(triggerEntity: TTriggerEntity, computedFieldMetadata: ComputedFieldMetadata<TContext>): Promise<void>;\n}\n\nexport interface ISolidDatabaseModule {\n name(): string;\n\n type(): DatasourceType;\n}\n\nexport enum EventType {\n USER_REGISTERED = 'user.registered',\n}\n\nexport class EventDetails<T> {\n constructor(\n public type: any,\n public payload: T,\n ) { }\n}\n\nexport interface IMail<TResponse = unknown> {\n sendEmail(\n to: string,\n subject: string,\n body: string,\n shouldQueueEmails: boolean,\n wrapperAttachments?: MailAttachmentWrapper[],\n attachments?: MailAttachment[],\n parentEntity?: any,\n parentEntityId?: any,\n cc?: string[],\n bcc?: string[],\n from?: string,\n ): Promise<TResponse>;\n\n sendEmailUsingTemplate(\n to: string,\n templateName: string,\n templateParams: any,\n shouldQueueEmails: boolean,\n wrapperAttachments?: MailAttachmentWrapper[],\n attachments?: MailAttachment[],\n parentEntity?: any,\n parentEntityId?: any,\n cc?: string[],\n bcc?: string[],\n from?: string,\n ): Promise<TResponse>;\n}\n\nexport interface ISMS {\n sendSMS(to: string, body: string, shouldQueueSms: boolean): Promise<any>;\n\n sendSMSUsingTemplate(\n to: string,\n templateName: string,\n templateParams: any,\n shouldQueueSms: boolean,\n ): Promise<any>;\n}\n\nexport interface IWhatsAppTransport {\n sendWhatsAppMessage(\n to: string,\n templateId: string,\n parameters: any,\n parentEntity?: any,\n parentEntityId?: any\n ): Promise<any>;\n}\n\nexport interface MailAttachmentWrapper {\n relativePath?: string;\n attachment?: MailAttachment;\n}\n\nexport interface MailAttachment {\n filename: string;\n templatePath?: string; // deprecated\n templateParams?: any; // deprecated\n content?: string | Buffer;\n contentType?: string;\n path?: string; //Filesystem absolute path or URL. \n}\n\nexport enum BrokerType {\n RabbitMQ = 'rabbitmq',\n Database = 'database'\n}\n\nexport interface QueuesModuleOptions {\n name: string;\n type: BrokerType;\n queueName: string;\n prefetch?: number;\n}\n\nexport type MediaWithFullUrl = Media & {\n _full_url: string;\n};\n\n\nexport type ErrorCode = string;\n\nexport type ErrorMeta = {\n message: string;\n httpStatus?: number;\n};\n\nexport type ErrorRule = {\n /** Canonical error code. Keep them kebab-case for consistency. */\n code: ErrorCode;\n /** Higher runs earlier. Defaults to 0 if not provided. */\n priority?: number;\n /** Return true if this rule matches the combined error text. */\n match: (combinedErrorText: string) => boolean;\n /** Display + HTTP mapping for this code. */\n meta: ErrorMeta;\n};\n\nexport interface IErrorCodeProvider {\n /** Used for registry identity & logs */\n name(): string;\n\n /**\n * Return all rules this provider contributes.\n * These will be merged with other providers’ rules, then sorted by priority.\n */\n rules(): ReadonlyArray<ErrorRule>;\n\n /**\n * Optional fallback meta for codes this provider owns (when called by getMessage/getHttpStatus).\n * If omitted, the ErrorMapperService will rely on the rule.meta of the first matching rule.\n */\n resolve?(code: ErrorCode): ErrorMeta | undefined;\n}\n\n// MCP Tool Related\n\nexport type PlanStep = CreateNewFileStep | RegisterNestProviderStep | AddMethodToExistingClassStep | RegisterSolidXExtensionComponentStep | AddListViewButtonStep | AddFormViewButtonStep | AddImportStep;\nexport interface AddImportStep {\n type: \"addImport\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n importStatement: string; // e.g. import { Something } from 'somewhere';\n overwrite?: boolean; // default=false\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface CreateNewFileStep {\n type: \"createNewFile\";\n path: string; // repo-relative e.g. solid-api/api/src/computed-providers/foo.provider.ts\n content: string; // full file content\n overwrite?: boolean; // default=false\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface RegisterNestProviderStep {\n type: \"registerNestProvider\";\n modulePath: string; // e.g. apps/api/src/address-master/address-master.module.ts\n providerClassName: string; // e.g. StateTotalCitiesComputedFieldProvider\n importFrom: string; // e.g. \"@/computed-providers/state-total-cities.provider\"\n registerIn: Array<\"providers\" | \"exports\">; // which arrays to add to\n uniqueGuard?: boolean; // default=true\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface AddMethodToExistingClassStep {\n type: \"addMethodToExistingClass\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n className: string // e.g. CountryService\n methodName: string // e.g. addCountry\n content: string // Full Method Code\n importStatements?: string[]; // e.g. [ \"import { X } from 'y';\" ]\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface RegisterSolidXExtensionComponentStep {\n type: \"registerSolidXExtensionComponent\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n content?: string; // Code\n importExtensionComponent?: string;\n}\n\nexport interface AddListViewButtonStep {\n type: \"addListViewButton\";\n moduleName?: string;\n modelName?: string;\n buttonType?: string;\n content?: string; // Code\n}\n\nexport interface AddFormViewButtonStep {\n type: \"addFormViewButton\";\n moduleName?: string;\n modelName?: string;\n buttonType?: string;\n content?: string; // Code\n}\n\nexport interface McpComputedProviderResponse {\n plan: PlanStep[];\n // provider?: any; // (intentionally ignored per your note)\n}\n\nexport interface ISecurityRuleConfigProvider {\n securityRuleConfig(activeUser: ActiveUserData, securityRule: SecurityRule): Promise<SecurityRuleConfig>;\n}\n\n\nexport interface AwsS3Config {\n S3_AWS_ACCESS_KEY: string;\n S3_AWS_SECRET_KEY: string;\n S3_AWS_REGION_NAME: string;\n}\n\n// Prevents inference so callers must provide explicit type arguments; reusable for other APIs.\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n"]}
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";;;AA4DA,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,wCAAwB,CAAA;IACxB,6DAA6C,CAAA;IAC7C,6DAA6C,CAAA;IAC7C,8CAA8B,CAAA;AAChC,CAAC,EALW,YAAY,4BAAZ,YAAY,QAKvB;AA0HD,IAAY,SAEX;AAFD,WAAY,SAAS;IACnB,gDAAmC,CAAA;AACrC,CAAC,EAFW,SAAS,yBAAT,SAAS,QAEpB;AAED,MAAa,YAAY;IACvB,YACS,IAAS,EACT,OAAU;QADV,SAAI,GAAJ,IAAI,CAAK;QACT,YAAO,GAAP,OAAO,CAAG;IACf,CAAC;CACN;AALD,oCAKC;AAmED,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,mCAAqB,CAAA;IACrB,mCAAqB,CAAA;AACvB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB","sourcesContent":["import { CreateEmailTemplateDto } from 'src/dtos/create-email-template.dto';\nimport { CreateSmsTemplateDto } from 'src/dtos/create-sms-template.dto';\nimport { SignUpDto } from 'src/dtos/sign-up.dto';\nimport { Readable } from 'stream';\nimport { CreateMediaStorageProviderMetadataDto } from './dtos/create-media-storage-provider-metadata.dto';\nimport { DatasourceType } from './dtos/create-model-metadata.dto';\nimport { CreateModuleMetadataDto } from './dtos/create-module-metadata.dto';\nimport { CreateRoleMetadataDto } from './dtos/create-role-metadata.dto';\nimport { CreateSecurityRuleDto } from './dtos/create-security-rule.dto';\nimport { FieldMetadata } from './entities/field-metadata.entity';\nimport { Media } from './entities/media.entity';\nimport { DashboardQuestion } from './entities/dashboard-question.entity';\nimport { ComputedFieldMetadata } from './helpers/solid-registry';\nimport { SqlExpression } from './services/question-data-providers/chartjs-sql-data-provider.service';\nimport { CreateDashboardDto } from './dtos/create-dashboard.dto';\nimport { AiInteraction } from './entities/ai-interaction.entity';\nimport { ActiveUserData } from './interfaces/active-user-data.interface';\nimport { SecurityRuleConfig } from './dtos/security-rule-config.dto';\nimport { SecurityRule } from './entities/security-rule.entity';\n\nexport interface FieldCrudManager {\n // fieldMetadata: FieldMetadata;\n // entityManager?: EntityManager;\n // createDto: any;\n // files : Array<Express.Multer.File>;\n validate(\n dto: any,\n files: Array<Express.Multer.File>,\n ): ValidationError[] | Promise<ValidationError[]>;\n transformForCreate(dto: any, ctxt?: any): any | Promise<any>;\n}\n\nexport interface ValidationError {\n field: string;\n error: string;\n}\n\n// export interface MediaStorage\nexport interface MediaStorageProvider<T> {\n store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;\n retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;\n // delete(file: string): Promise<void>;\n}\n\nexport interface ModuleMetadataConfiguration {\n moduleMetadata?: CreateModuleMetadataDto,\n roles?: CreateRoleMetadataDto[],\n users?: SignUpDto[],\n actions?: any[],\n menus?: any[],\n views?: any[],\n emailTemplates?: CreateEmailTemplateDto[],\n smsTemplates?: CreateSmsTemplateDto[],\n mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]\n securityRules?: CreateSecurityRuleDto[],\n dashboards?: CreateDashboardDto[],\n}\n\nexport enum SettingLevel {\n SystemEnv = 'system-env',\n SystemAdminReadonly = 'system-admin-readonly',\n SystemAdminEditable = 'system-admin-editable',\n InternalUser = \"internal-user\"\n}\n\nexport interface SettingDefinition<T = any> {\n moduleName: string;\n key: string;\n value: T;\n level: SettingLevel;\n}\n\n// solid-core/settings/settings-provider.interface.ts\nexport interface ISettingsProvider {\n getSettings(): SettingDefinition[];\n}\n\nexport interface CodeGenerationOptions {\n moduleId?: number;\n moduleUserKey?: string;\n modelId?: number;\n modelUserKey?: string;\n fieldIdsForRemoval?: number[];\n fieldNamesForRemoval?: string[];\n dryRun?: boolean;\n fieldIdsForRefresh?: number[];\n fieldNamesForRefresh?: string[];\n}\n\nexport interface TriggerMcpClientOptions {\n aiInteractionId: number;\n moduleName: string;\n}\n\nexport interface McpResponse {\n success: boolean;\n request: string;\n response: string;\n model?: string;\n tools_invoked?: string[];\n tool_calls?: any[];\n duration_ms?: number;\n errors?: string[];\n error_trace?: string[];\n content_type?: string;\n}\n\nexport interface ISelectionProviderContext {\n limit: number;\n offset: number;\n formValues: Record<string, any>;\n //Attribute to control the validation on creating the record\n validateOnSave?: boolean;\n // query: string;\n}\n\nexport interface ISelectionProviderValues {\n label: string;\n value: string;\n}\n\nexport interface ISelectionProvider<T extends ISelectionProviderContext> {\n help(): string;\n\n name(): string;\n\n value(optionValue: string, ctxt: T): Promise<ISelectionProviderValues | any>;\n\n values(query: any, ctxt: T): Promise<readonly ISelectionProviderValues[]>;\n}\n\nexport interface IDashboardVariableSelectionProvider<T extends ISelectionProviderContext> extends ISelectionProvider<T> {\n}\n\nexport interface IMcpToolResponseHandler {\n apply(aiInteraction: AiInteraction);\n}\n\nexport interface QuestionSqlDataProviderContext {\n // questionSqlDatasetConfig: QuestionSqlDatasetConfig;\n // questionId: number;\n // question: Question;\n expressions?: SqlExpression[]\n}\nexport interface IDashboardQuestionDataProvider<TContext, TData> {\n help(): string;\n\n name(): string;\n\n getData(question: DashboardQuestion, ctxt?: TContext): Promise<TData[] | TData>;\n}\n\n/**\n * @deprecated Use `IEntityComputedFieldProvider` instead.\n */\nexport interface IComputedFieldProvider<T> {\n help(): string;\n\n name(): string;\n\n valueType(): string;\n\n computeValue(dto: any, ctxt: T): Promise<string | number>; // FIXME : Improve the types to make it more specific using generics\n}\n\nexport interface IEntityComputedFieldProvider {\n help(): string;\n\n name(): string;\n}\n\nexport interface IEntityPreComputeFieldProvider<TTriggerEntity, TContext, TValue = void> extends IEntityComputedFieldProvider {\n preComputeValue(triggerEntity: TTriggerEntity, computedFieldMetadata: ComputedFieldMetadata<TContext>): Promise<TValue>;\n}\n\nexport interface IEntityPostComputeFieldProvider<TTriggerEntity, TContext> extends IEntityComputedFieldProvider {\n postComputeAndSaveValue(triggerEntity: TTriggerEntity, computedFieldMetadata: ComputedFieldMetadata<TContext>): Promise<void>;\n}\n\nexport interface ISolidDatabaseModule {\n name(): string;\n\n type(): DatasourceType;\n}\n\nexport enum EventType {\n USER_REGISTERED = 'user.registered',\n}\n\nexport class EventDetails<T> {\n constructor(\n public type: any,\n public payload: T,\n ) { }\n}\n\nexport interface IMail<TResponse = unknown> {\n sendEmail(\n to: string,\n subject: string,\n body: string,\n shouldQueueEmails: boolean,\n wrapperAttachments?: MailAttachmentWrapper[],\n attachments?: MailAttachment[],\n parentEntity?: any,\n parentEntityId?: any,\n cc?: string[],\n bcc?: string[],\n from?: string,\n ): Promise<TResponse>;\n\n sendEmailUsingTemplate(\n to: string,\n templateName: string,\n templateParams: any,\n shouldQueueEmails: boolean,\n wrapperAttachments?: MailAttachmentWrapper[],\n attachments?: MailAttachment[],\n parentEntity?: any,\n parentEntityId?: any,\n cc?: string[],\n bcc?: string[],\n from?: string,\n ): Promise<TResponse>;\n}\n\nexport interface ISMS {\n sendSMS(to: string, body: string, shouldQueueSms: boolean): Promise<any>;\n\n sendSMSUsingTemplate(\n to: string,\n templateName: string,\n templateParams: any,\n shouldQueueSms: boolean,\n ): Promise<any>;\n}\n\nexport interface IWhatsAppTransport {\n sendWhatsAppMessage(\n to: string,\n templateId: string,\n parameters: any,\n parentEntity?: any,\n parentEntityId?: any\n ): Promise<any>;\n}\n\nexport interface MailAttachmentWrapper {\n relativePath?: string;\n attachment?: MailAttachment;\n}\n\nexport interface MailAttachment {\n filename: string;\n templatePath?: string; // deprecated\n templateParams?: any; // deprecated\n content?: string | Buffer;\n contentType?: string;\n path?: string; //Filesystem absolute path or URL. \n}\n\nexport enum BrokerType {\n RabbitMQ = 'rabbitmq',\n Database = 'database'\n}\n\nexport interface QueuesModuleOptions {\n name: string;\n type: BrokerType;\n queueName: string;\n prefetch?: number;\n persistToDatabase?: boolean;\n}\n\nexport type MediaWithFullUrl = Media & {\n _full_url: string;\n};\n\n\nexport type ErrorCode = string;\n\nexport type ErrorMeta = {\n message: string;\n httpStatus?: number;\n};\n\nexport type ErrorRule = {\n /** Canonical error code. Keep them kebab-case for consistency. */\n code: ErrorCode;\n /** Higher runs earlier. Defaults to 0 if not provided. */\n priority?: number;\n /** Return true if this rule matches the combined error text. */\n match: (combinedErrorText: string) => boolean;\n /** Display + HTTP mapping for this code. */\n meta: ErrorMeta;\n};\n\nexport interface IErrorCodeProvider {\n /** Used for registry identity & logs */\n name(): string;\n\n /**\n * Return all rules this provider contributes.\n * These will be merged with other providers’ rules, then sorted by priority.\n */\n rules(): ReadonlyArray<ErrorRule>;\n\n /**\n * Optional fallback meta for codes this provider owns (when called by getMessage/getHttpStatus).\n * If omitted, the ErrorMapperService will rely on the rule.meta of the first matching rule.\n */\n resolve?(code: ErrorCode): ErrorMeta | undefined;\n}\n\n// MCP Tool Related\n\nexport type PlanStep = CreateNewFileStep | RegisterNestProviderStep | AddMethodToExistingClassStep | RegisterSolidXExtensionComponentStep | AddListViewButtonStep | AddFormViewButtonStep | AddImportStep;\nexport interface AddImportStep {\n type: \"addImport\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n importStatement: string; // e.g. import { Something } from 'somewhere';\n overwrite?: boolean; // default=false\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface CreateNewFileStep {\n type: \"createNewFile\";\n path: string; // repo-relative e.g. solid-api/api/src/computed-providers/foo.provider.ts\n content: string; // full file content\n overwrite?: boolean; // default=false\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface RegisterNestProviderStep {\n type: \"registerNestProvider\";\n modulePath: string; // e.g. apps/api/src/address-master/address-master.module.ts\n providerClassName: string; // e.g. StateTotalCitiesComputedFieldProvider\n importFrom: string; // e.g. \"@/computed-providers/state-total-cities.provider\"\n registerIn: Array<\"providers\" | \"exports\">; // which arrays to add to\n uniqueGuard?: boolean; // default=true\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface AddMethodToExistingClassStep {\n type: \"addMethodToExistingClass\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n className: string // e.g. CountryService\n methodName: string // e.g. addCountry\n content: string // Full Method Code\n importStatements?: string[]; // e.g. [ \"import { X } from 'y';\" ]\n rationale?: string; // optional, ignored by executor\n}\n\nexport interface RegisterSolidXExtensionComponentStep {\n type: \"registerSolidXExtensionComponent\";\n path: string; // e.g. apps/api/src/address-master/services/address-master.service.ts\n content?: string; // Code\n importExtensionComponent?: string;\n}\n\nexport interface AddListViewButtonStep {\n type: \"addListViewButton\";\n moduleName?: string;\n modelName?: string;\n buttonType?: string;\n content?: string; // Code\n}\n\nexport interface AddFormViewButtonStep {\n type: \"addFormViewButton\";\n moduleName?: string;\n modelName?: string;\n buttonType?: string;\n content?: string; // Code\n}\n\nexport interface McpComputedProviderResponse {\n plan: PlanStep[];\n // provider?: any; // (intentionally ignored per your note)\n}\n\nexport interface ISecurityRuleConfigProvider {\n securityRuleConfig(activeUser: ActiveUserData, securityRule: SecurityRule): Promise<SecurityRuleConfig>;\n}\n\n\nexport interface AwsS3Config {\n S3_AWS_ACCESS_KEY: string;\n S3_AWS_SECRET_KEY: string;\n S3_AWS_REGION_NAME: string;\n}\n\n// Prevents inference so callers must provide explicit type arguments; reusable for other APIs.\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed-field-evaluation-queue-options.d.ts","sourceRoot":"","sources":["../../src/jobs/computed-field-evaluation-queue-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"computed-field-evaluation-queue-options.d.ts","sourceRoot":"","sources":["../../src/jobs/computed-field-evaluation-queue-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;;;;;;;;AAI3C,wBAME"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed-field-evaluation-queue-options.js","sourceRoot":"","sources":["../../src/jobs/computed-field-evaluation-queue-options.ts"],"names":[],"mappings":";;AAAA,8CAA2C;AAE3C,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAE3D,kBAAe;IACX,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,uBAAU,CAAC,QAAQ;IACzB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"computed-field-evaluation-queue-options.js","sourceRoot":"","sources":["../../src/jobs/computed-field-evaluation-queue-options.ts"],"names":[],"mappings":";;AAAA,8CAA2C;AAE3C,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAE3D,kBAAe;IACX,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,uBAAU,CAAC,QAAQ;IACzB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,EAAE;IACZ,iBAAiB,EAAE,KAAK;CAC3B,CAAC","sourcesContent":["import { BrokerType } from \"../interfaces\";\n\nconst QUEUE_NAME = 'solid_computed_field_evaluation_queue';\n\nexport default {\n name: QUEUE_NAME,\n type: BrokerType.RabbitMQ,\n queueName: QUEUE_NAME,\n prefetch: 10,\n persistToDatabase: false,\n};\n"]}
|
|
@@ -14,6 +14,7 @@ export declare abstract class RabbitMqPublisher<T> implements OnModuleDestroy, Q
|
|
|
14
14
|
private connectingPromise;
|
|
15
15
|
constructor(mqMessageService: MqMessageService, mqMessageQueueService: MqMessageQueueService);
|
|
16
16
|
abstract options(): QueuesModuleOptions;
|
|
17
|
+
protected shouldPersistToDatabase(): boolean;
|
|
17
18
|
private ensureConnectionAndChannel;
|
|
18
19
|
onModuleDestroy(): Promise<void>;
|
|
19
20
|
private closeConnectionAndChannel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-publisher.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-publisher.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,8BAAsB,iBAAiB,CAAC,CAAC,CAAE,YAAW,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;IAWhF,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB;IACrD,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IAXnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAGrC,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,iBAAiB,CAA8B;gBAGhC,gBAAgB,EAAE,gBAAgB,EAClC,qBAAqB,EAAE,qBAAqB;IAanE,QAAQ,CAAC,OAAO,IAAI,mBAAmB;
|
|
1
|
+
{"version":3,"file":"rabbitmq-publisher.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-publisher.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,8BAAsB,iBAAiB,CAAC,CAAC,CAAE,YAAW,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;IAWhF,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB;IACrD,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IAXnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAGrC,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,iBAAiB,CAA8B;gBAGhC,gBAAgB,EAAE,gBAAgB,EAClC,qBAAqB,EAAE,qBAAqB;IAanE,QAAQ,CAAC,OAAO,IAAI,mBAAmB;IAEvC,SAAS,CAAC,uBAAuB,IAAI,OAAO;YAI9B,0BAA0B;IAwElC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;YAIxB,yBAAyB;IA0BjC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YA+D1C,iBAAiB;CA0BlC"}
|
|
@@ -55,6 +55,9 @@ class RabbitMqPublisher {
|
|
|
55
55
|
this.logger.debug('Queue service Role is not defined in the environment variables');
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
shouldPersistToDatabase() {
|
|
59
|
+
return this.options().persistToDatabase ?? true;
|
|
60
|
+
}
|
|
58
61
|
async ensureConnectionAndChannel() {
|
|
59
62
|
if (this.channel) {
|
|
60
63
|
return this.channel;
|
|
@@ -160,7 +163,9 @@ class RabbitMqPublisher {
|
|
|
160
163
|
if (!message.retryInterval)
|
|
161
164
|
message.retryInterval = 1000;
|
|
162
165
|
message.messageId = (0, uuid_1.v4)();
|
|
163
|
-
|
|
166
|
+
if (this.shouldPersistToDatabase()) {
|
|
167
|
+
await this.persistToDatabase(namespacedQueueName, message);
|
|
168
|
+
}
|
|
164
169
|
try {
|
|
165
170
|
const publishStatus = channel.publish(exchangeName, routingKey, Buffer.from(JSON.stringify(message)), { mandatory: true });
|
|
166
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-publisher.service.js","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-publisher.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, OnModuleDestroy } from '@nestjs/common';\nimport * as amqp from 'amqplib';\nimport { v4 as uuidv4 } from 'uuid';\nimport { QueuesModuleOptions } from \"../../interfaces\";\nimport { QueueMessage, QueuePublisher } from '../../interfaces/mq';\nimport { MqMessageQueueService } from '../mq-message-queue.service';\nimport { MqMessageService } from '../mq-message.service';\nimport { buildNamespacedQueueName } from './common';\n\nexport abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePublisher<T> {\n private readonly logger = new Logger(RabbitMqPublisher.name);\n private readonly url: string;\n private readonly serviceRole: string;\n\n // Maintain connection...\n private connection: amqp.Connection | null = null;\n private channel: amqp.Channel | null = null;\n private connectingPromise: Promise<void> | null = null;\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(`RabbitMqPublisher instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n\n abstract options(): QueuesModuleOptions;\n\n private async ensureConnectionAndChannel(): Promise<amqp.Channel> {\n if (this.channel) {\n return this.channel;\n }\n\n // If another call is already connecting, wait for it\n if (this.connectingPromise) {\n await this.connectingPromise;\n if (this.channel) return this.channel;\n }\n\n this.connectingPromise = (async () => {\n const url = new URL(this.url);\n\n const conn = await amqp.connect({\n protocol: url.protocol.replace(':', ''), // \"amqps\"\n hostname: url.hostname,\n port: parseInt(url.port),\n username: url.username,\n // Node's URL already decodes percent-encoding; decodeURIComponent is not needed\n // But without it does not seem to be working...\n password: decodeURIComponent(url.password),\n frameMax: 131072,\n });\n\n conn.on('error', (err) => {\n this.logger.error(`RabbitMQ connection error: ${err.message}`, err.stack);\n });\n\n conn.on('close', () => {\n this.logger.warn('RabbitMQ connection closed, resetting');\n this.connection = null;\n this.channel = null;\n });\n\n const channel = await conn.createChannel();\n\n channel.on('return', (msg) => {\n const content = msg.content?.toString?.() ?? '';\n this.logger.warn(\n `RabbitMqPublisher message returned from exchange ${msg.fields.exchange} with routingKey ${msg.fields.routingKey}: ${content}`,\n );\n });\n\n const options = this.options();\n const queueName = options.queueName;\n const namespacedQueueName = buildNamespacedQueueName(queueName);\n const exchangeName = `${namespacedQueueName}.exchange`;\n const routingKey = `${namespacedQueueName}.routing-key`;\n\n await channel.assertExchange(exchangeName, 'direct', {});\n const queue = await channel.assertQueue(namespacedQueueName, {});\n await channel.bindQueue(queue.queue, exchangeName, routingKey);\n\n this.connection = conn;\n this.channel = channel;\n })();\n\n try {\n await this.connectingPromise;\n } finally {\n this.connectingPromise = null;\n }\n\n if (!this.channel) {\n throw new Error('Failed to initialize RabbitMQ channel');\n }\n\n return this.channel;\n }\n\n // Nest will call this for every subclass instance, because they inherit the method\n async onModuleDestroy(): Promise<void> {\n await this.closeConnectionAndChannel();\n }\n\n private async closeConnectionAndChannel(): Promise<void> {\n if (this.channel) {\n try {\n await this.channel.close();\n } catch (err) {\n this.logger.warn(\n `RabbitMqPublisher error closing channel: ${(err as Error).message}`,\n );\n } finally {\n this.channel = null;\n }\n }\n\n if (this.connection) {\n try {\n await this.connection.close();\n } catch (err) {\n this.logger.warn(\n `RabbitMqPublisher error closing connection: ${(err as Error).message}`,\n );\n } finally {\n this.connection = null;\n }\n }\n }\n\n async publish(message: QueueMessage<T>): Promise<string> {\n if (!this.url) {\n this.logger.error('RabbitMqPublisher url is not defined in the environment variables');\n throw new Error('RabbitMqPublisher url is not defined in the environment variables');\n }\n if (!this.serviceRole) {\n this.logger.error('Queue service Role is not defined in the environment variables');\n throw new Error('Queue service Role is not defined in the environment variables');\n }\n if (this.serviceRole === 'subscriber') {\n this.logger.error('Queue service Role is subscriber, cannot publish messages');\n throw new Error('Queue service Role is subscriber, cannot publish messages');\n }\n\n const channel = await this.ensureConnectionAndChannel();\n // this.logger.debug(`RabbitMqPublisher publisher channel created options: ${JSON.stringify(this.options())} and url: ${url}`);\n\n const options = this.options();\n\n const queueName = options.queueName;\n const namespacedQueueName = buildNamespacedQueueName(queueName);\n\n const exchangeName = `${namespacedQueueName}.exchange`;\n const routingKey = `${namespacedQueueName}.routing-key`;\n\n // Set default values for retry. \n // by default there are no retries.\n if (!message.retryCount) message.retryCount = 0;\n if (!message.retryInterval) message.retryInterval = 1000;\n\n // generate a new message id \n message.messageId = uuidv4();\n\n // Save the message to the DB so that we can then change its status in the subscriber...\n await this.persistToDatabase(namespacedQueueName, message);\n\n // wait for the channel to confirm \n try {\n // Publish the message\n // const publishStatus = channel.publish(exchangeName, routingKey, Buffer.from(JSON.stringify(message)));\n const publishStatus = channel.publish(exchangeName, routingKey, Buffer.from(JSON.stringify(message)), { mandatory: true });\n // this.logger.debug(`RabbitMqPublisher publish status: ${JSON.stringify(publishStatus)}`);\n // if (!publishStatus) {\n // this.logger.warn('RabbitMqPublisher Message buffering failed!');\n // }\n // await channel.waitForConfirms();\n // this.logger.debug('RabbitMqPublisher Message published successfully');\n } catch (err) {\n this.logger.error(`RabbitMqPublisher Message publish failed: ${JSON.stringify(err)}`);\n if (err instanceof Error) {\n this.logger.error(`RabbitMqPublisher Error stack: ${err.stack}`);\n }\n }\n finally {\n }\n // this.logger.debug(`Sent message: ${JSON.stringify(message)}`);\n\n // return the newly created message id.\n return message.messageId;\n }\n\n private async persistToDatabase(queueName: string, message: QueueMessage<T>) {\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 mqMessageQueue = await this.mqMessageQueueService.resolveQueue(queueName);\n\n // 2. Next create an entry in the mqMessage table. \n await this.mqMessageService.create({\n messageBroker: this.options().type,\n messageId: message.messageId,\n retryCount: message.retryCount,\n retryInterval: message.retryInterval,\n stage: 'pending',\n startedAt: new Date(),\n input: JSON.stringify(message, null, 2),\n parentEntityId: message.parentEntityId,\n parentEntity: message.parentEntity,\n mqMessageQueueId: mqMessageQueue.id,\n });\n }\n catch (error) {\n this.logger.error(error.message, error.stack);\n }\n\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rabbitmq-publisher.service.js","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-publisher.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger, OnModuleDestroy } from '@nestjs/common';\nimport * as amqp from 'amqplib';\nimport { v4 as uuidv4 } from 'uuid';\nimport { QueuesModuleOptions } from \"../../interfaces\";\nimport { QueueMessage, QueuePublisher } from '../../interfaces/mq';\nimport { MqMessageQueueService } from '../mq-message-queue.service';\nimport { MqMessageService } from '../mq-message.service';\nimport { buildNamespacedQueueName } from './common';\n\nexport abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePublisher<T> {\n private readonly logger = new Logger(RabbitMqPublisher.name);\n private readonly url: string;\n private readonly serviceRole: string;\n\n // Maintain connection...\n private connection: amqp.Connection | null = null;\n private channel: amqp.Channel | null = null;\n private connectingPromise: Promise<void> | null = null;\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(`RabbitMqPublisher instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);\n }\n\n abstract options(): QueuesModuleOptions;\n\n protected shouldPersistToDatabase(): boolean {\n return this.options().persistToDatabase ?? true;\n }\n\n private async ensureConnectionAndChannel(): Promise<amqp.Channel> {\n if (this.channel) {\n return this.channel;\n }\n\n // If another call is already connecting, wait for it\n if (this.connectingPromise) {\n await this.connectingPromise;\n if (this.channel) return this.channel;\n }\n\n this.connectingPromise = (async () => {\n const url = new URL(this.url);\n\n const conn = await amqp.connect({\n protocol: url.protocol.replace(':', ''), // \"amqps\"\n hostname: url.hostname,\n port: parseInt(url.port),\n username: url.username,\n // Node's URL already decodes percent-encoding; decodeURIComponent is not needed\n // But without it does not seem to be working...\n password: decodeURIComponent(url.password),\n frameMax: 131072,\n });\n\n conn.on('error', (err) => {\n this.logger.error(`RabbitMQ connection error: ${err.message}`, err.stack);\n });\n\n conn.on('close', () => {\n this.logger.warn('RabbitMQ connection closed, resetting');\n this.connection = null;\n this.channel = null;\n });\n\n const channel = await conn.createChannel();\n\n channel.on('return', (msg) => {\n const content = msg.content?.toString?.() ?? '';\n this.logger.warn(\n `RabbitMqPublisher message returned from exchange ${msg.fields.exchange} with routingKey ${msg.fields.routingKey}: ${content}`,\n );\n });\n\n const options = this.options();\n const queueName = options.queueName;\n const namespacedQueueName = buildNamespacedQueueName(queueName);\n const exchangeName = `${namespacedQueueName}.exchange`;\n const routingKey = `${namespacedQueueName}.routing-key`;\n\n await channel.assertExchange(exchangeName, 'direct', {});\n const queue = await channel.assertQueue(namespacedQueueName, {});\n await channel.bindQueue(queue.queue, exchangeName, routingKey);\n\n this.connection = conn;\n this.channel = channel;\n })();\n\n try {\n await this.connectingPromise;\n } finally {\n this.connectingPromise = null;\n }\n\n if (!this.channel) {\n throw new Error('Failed to initialize RabbitMQ channel');\n }\n\n return this.channel;\n }\n\n // Nest will call this for every subclass instance, because they inherit the method\n async onModuleDestroy(): Promise<void> {\n await this.closeConnectionAndChannel();\n }\n\n private async closeConnectionAndChannel(): Promise<void> {\n if (this.channel) {\n try {\n await this.channel.close();\n } catch (err) {\n this.logger.warn(\n `RabbitMqPublisher error closing channel: ${(err as Error).message}`,\n );\n } finally {\n this.channel = null;\n }\n }\n\n if (this.connection) {\n try {\n await this.connection.close();\n } catch (err) {\n this.logger.warn(\n `RabbitMqPublisher error closing connection: ${(err as Error).message}`,\n );\n } finally {\n this.connection = null;\n }\n }\n }\n\n async publish(message: QueueMessage<T>): Promise<string> {\n if (!this.url) {\n this.logger.error('RabbitMqPublisher url is not defined in the environment variables');\n throw new Error('RabbitMqPublisher url is not defined in the environment variables');\n }\n if (!this.serviceRole) {\n this.logger.error('Queue service Role is not defined in the environment variables');\n throw new Error('Queue service Role is not defined in the environment variables');\n }\n if (this.serviceRole === 'subscriber') {\n this.logger.error('Queue service Role is subscriber, cannot publish messages');\n throw new Error('Queue service Role is subscriber, cannot publish messages');\n }\n\n const channel = await this.ensureConnectionAndChannel();\n // this.logger.debug(`RabbitMqPublisher publisher channel created options: ${JSON.stringify(this.options())} and url: ${url}`);\n\n const options = this.options();\n\n const queueName = options.queueName;\n const namespacedQueueName = buildNamespacedQueueName(queueName);\n\n const exchangeName = `${namespacedQueueName}.exchange`;\n const routingKey = `${namespacedQueueName}.routing-key`;\n\n // Set default values for retry. \n // by default there are no retries.\n if (!message.retryCount) message.retryCount = 0;\n if (!message.retryInterval) message.retryInterval = 1000;\n\n // generate a new message id \n message.messageId = uuidv4();\n\n // Save the message to the DB so that we can then change its status in the subscriber...\n if (this.shouldPersistToDatabase()) {\n await this.persistToDatabase(namespacedQueueName, message);\n }\n\n // wait for the channel to confirm \n try {\n // Publish the message\n // const publishStatus = channel.publish(exchangeName, routingKey, Buffer.from(JSON.stringify(message)));\n const publishStatus = channel.publish(exchangeName, routingKey, Buffer.from(JSON.stringify(message)), { mandatory: true });\n // this.logger.debug(`RabbitMqPublisher publish status: ${JSON.stringify(publishStatus)}`);\n // if (!publishStatus) {\n // this.logger.warn('RabbitMqPublisher Message buffering failed!');\n // }\n // await channel.waitForConfirms();\n // this.logger.debug('RabbitMqPublisher Message published successfully');\n } catch (err) {\n this.logger.error(`RabbitMqPublisher Message publish failed: ${JSON.stringify(err)}`);\n if (err instanceof Error) {\n this.logger.error(`RabbitMqPublisher Error stack: ${err.stack}`);\n }\n }\n finally {\n }\n // this.logger.debug(`Sent message: ${JSON.stringify(message)}`);\n\n // return the newly created message id.\n return message.messageId;\n }\n\n private async persistToDatabase(queueName: string, message: QueueMessage<T>) {\n\n // make an entry in the relevant database table, generate a unique id earlier.\n try {\n // 1. resolve the queue first\n const mqMessageQueue = await this.mqMessageQueueService.resolveQueue(queueName);\n\n // 2. Next create an entry in the mqMessage table. \n await this.mqMessageService.create({\n messageBroker: this.options().type,\n messageId: message.messageId,\n retryCount: message.retryCount,\n retryInterval: message.retryInterval,\n stage: 'pending',\n startedAt: new Date(),\n input: JSON.stringify(message, null, 2),\n parentEntityId: message.parentEntityId,\n parentEntity: message.parentEntity,\n mqMessageQueueId: mqMessageQueue.id,\n });\n }\n catch (error) {\n this.logger.error(error.message, error.stack);\n }\n\n }\n}\n"]}
|
|
@@ -21,6 +21,7 @@ export declare abstract class RabbitMqSubscriber<T> implements OnModuleInit, Que
|
|
|
21
21
|
protected get logger(): Logger;
|
|
22
22
|
abstract subscribe(message: QueueMessage<T>): any;
|
|
23
23
|
abstract options(): QueuesModuleOptions;
|
|
24
|
+
protected shouldPersistToDatabase(): boolean;
|
|
24
25
|
establishConnection(): Promise<amqp.Connection>;
|
|
25
26
|
onModuleInit(): Promise<void>;
|
|
26
27
|
private connectAndConsume;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-subscriber.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,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;AAezD,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,eAAe,CAAC,CAAS;IACjC,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,SAAS,KAAK,aAAa,IAAI,MAAM,CAEpC;IAED,SAAS,KAAK,MAAM,IAAI,MAAM,CAK7B;IAED,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3C,QAAQ,CAAC,OAAO,IAAI,mBAAmB;
|
|
1
|
+
{"version":3,"file":"rabbitmq-subscriber.service.d.ts","sourceRoot":"","sources":["../../../src/services/queues/rabbitmq-subscriber.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,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;AAezD,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,eAAe,CAAC,CAAS;IACjC,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,SAAS,KAAK,aAAa,IAAI,MAAM,CAEpC;IAED,SAAS,KAAK,MAAM,IAAI,MAAM,CAK7B;IAED,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3C,QAAQ,CAAC,OAAO,IAAI,mBAAmB;IAEvC,SAAS,CAAC,uBAAuB,IAAI,OAAO;IAItC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAsB/C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YA2CrB,iBAAiB;YA8GjB,qBAAqB;YAiCrB,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,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAkBjG,sBAAsB;IAkCpC,OAAO,CAAC,0BAA0B;IAqBlC,OAAO,CAAC,gBAAgB;YASV,oBAAoB;CAuDrC"}
|
|
@@ -74,6 +74,9 @@ class RabbitMqSubscriber {
|
|
|
74
74
|
}
|
|
75
75
|
return this._loggerInstance;
|
|
76
76
|
}
|
|
77
|
+
shouldPersistToDatabase() {
|
|
78
|
+
return this.options().persistToDatabase ?? true;
|
|
79
|
+
}
|
|
77
80
|
async establishConnection() {
|
|
78
81
|
const url = new URL(this.url);
|
|
79
82
|
const connection = await amqp.connect({
|
|
@@ -218,7 +221,9 @@ class RabbitMqSubscriber {
|
|
|
218
221
|
const errorMessage = error?.message || String(error);
|
|
219
222
|
this.logger.error(`Error processing message on queue ${queueName}: ${errorMessage}`, error?.stack);
|
|
220
223
|
if (message.currentRetry < message.retryCount) {
|
|
221
|
-
|
|
224
|
+
if (this.shouldPersistToDatabase()) {
|
|
225
|
+
await this.updateStatusInDatabase('retrying', message);
|
|
226
|
+
}
|
|
222
227
|
message.currentRetry++;
|
|
223
228
|
const retryQueue = `${queueName}.retry`;
|
|
224
229
|
const payload = Buffer.from(JSON.stringify(message));
|
|
@@ -232,7 +237,9 @@ class RabbitMqSubscriber {
|
|
|
232
237
|
this.logger.warn(`Retrying message (${message.currentRetry}/${message.retryCount}) after ${message.retryInterval}ms on queue ${queueName}`);
|
|
233
238
|
return;
|
|
234
239
|
}
|
|
235
|
-
|
|
240
|
+
if (this.shouldPersistToDatabase()) {
|
|
241
|
+
await this.updateStatusInDatabase('failed', message, errorMessage, '');
|
|
242
|
+
}
|
|
236
243
|
channel.ack(rawMessage);
|
|
237
244
|
await this.publishToFailedQueue(queueName, Buffer.from(JSON.stringify(message)), channel, error);
|
|
238
245
|
this.logger.error(`Message failed after ${message.retryCount} attempts on queue ${queueName}: ${errorMessage}`);
|
|
@@ -317,10 +324,14 @@ class RabbitMqSubscriber {
|
|
|
317
324
|
return Math.min(maxMs, exp + jitter);
|
|
318
325
|
}
|
|
319
326
|
async processMessage(message, rawMessage, channel, queueName) {
|
|
320
|
-
|
|
327
|
+
if (this.shouldPersistToDatabase()) {
|
|
328
|
+
await this.updateStatusInDatabase('started', message);
|
|
329
|
+
}
|
|
321
330
|
const result = await this.subscribeWithTimeout(message, queueName);
|
|
322
331
|
channel.ack(rawMessage);
|
|
323
|
-
|
|
332
|
+
if (this.shouldPersistToDatabase()) {
|
|
333
|
+
await this.updateStatusInDatabase('succeeded', message, '', result ? JSON.stringify(result, null, 2) : '');
|
|
334
|
+
}
|
|
324
335
|
}
|
|
325
336
|
async updateStatusInDatabase(stage, message, error = '', result = '') {
|
|
326
337
|
try {
|
|
@@ -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';\nimport { buildNamespacedQueueName } from './common';\n\nclass ConsumerProcessingTimeoutError extends Error {\n constructor(\n readonly queueName: string,\n readonly messageId: string,\n readonly timeoutMs: number,\n ) {\n super(`Subscriber processing timed out after ${timeoutMs}ms for queue ${queueName} and messageId ${messageId}`);\n this.name = 'ConsumerProcessingTimeoutError';\n }\n}\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 _loggerInstance?: Logger;\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 protected get loggerContext(): string {\n return this.constructor.name;\n }\n\n protected get logger(): Logger {\n if (!this._loggerInstance) {\n this._loggerInstance = new Logger(this.loggerContext);\n }\n return this._loggerInstance;\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 const roleAllowed = ['both', 'subscriber'].includes(this.serviceRole);\n\n if (!roleAllowed) {\n this.logger.log(`RabbitMqSubscriber is disabled because QUEUES_SERVICE_ROLE is \"${this.serviceRole}\". Expected \"both\" or \"subscriber\".`);\n return;\n }\n\n // we will start subscriber only if the current service role is subscriber. \n if (this.url && 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 const namespacedQueueName = buildNamespacedQueueName(queueName);\n try {\n await this.connectAndConsume(namespacedQueueName);\n } catch (err) {\n this.logger.error(`Failed to connect to RabbitMQ for queue ${namespacedQueueName}: ${(err as Error).message}`, (err as Error).stack);\n this.triggerReconnect(namespacedQueueName, 'initial connection failure');\n }\n\n this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(options)} and url: ${this.url}`);\n }\n }\n\n private async connectAndConsume(queueName: string): Promise<void> {\n await this.cleanup();\n this.logger.log(`RabbitMqSubscriber in connectAndConsume for queue: ${queueName} and url: ${this.url}`);\n\n const options = this.options();\n const prefetch = options.prefetch ?? 1;\n if (prefetch < 1) {\n throw new Error(`RabbitMqSubscriber prefetch must be >= 1 for queue ${queueName}`);\n }\n const processingTimeoutMs = this.resolveProcessingTimeoutMs();\n if (processingTimeoutMs > 0) {\n this.logger.log(`RabbitMqSubscriber using processing timeout ${processingTimeoutMs}ms for queue ${queueName}`);\n }\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(prefetch);\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 let message: QueueMessage<T> = null;\n\n try {\n const messageContentString = rawMessage.content.toString();\n message = JSON.parse(messageContentString) as QueueMessage<T>;\n this.logger.debug(`rabbitmq subscriber received message with id: ${message.messageId} for queue ${queueName}`);\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, queueName);\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}`, (error as Error)?.stack);\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, queueName: string): Promise<void> {\n await this.updateStatusInDatabase('started', message);\n\n // Capture the results of handling the task.\n const result = await this.subscribeWithTimeout(message, queueName);\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 private resolveProcessingTimeoutMs(): number {\n // Broker-side delivery-ack timeout (ms). If not provided, assume RabbitMQ default\n // behavior used in this project: 30 minutes.\n // Example (RabbitMQ broker):\n // - Broker ack timeout: 30m => 1,800,000ms (QUEUES_RABBITMQ_CONSUMER_ACK_TIMEOUT_MS)\n // - App soft timeout should be slightly lower, e.g. 29m30s => 1,770,000ms\n // (QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS), so application code fails first,\n // records DB state/error, and avoids broker-forced channel close as primary failure signal.\n const brokerTimeoutMs = this.parsePositiveInt(process.env.QUEUES_RABBITMQ_CONSUMER_ACK_TIMEOUT_MS, 30 * 60 * 1000);\n\n // Soft timeout should fire *before* broker timeout so we can fail explicitly,\n // persist status/error, and avoid broker-forced channel closure as primary signal.\n // Keep at least 1s to avoid zero/negative values when broker timeout is very small.\n const defaultSoftTimeoutMs = Math.max(1_000, brokerTimeoutMs - 30_000);\n\n // Final timeout precedence:\n // 1) QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS (if valid positive int)\n // 2) Derived defaultSoftTimeoutMs (broker timeout - 30s)\n return this.parsePositiveInt(process.env.QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS, defaultSoftTimeoutMs);\n }\n\n private parsePositiveInt(value: string | undefined, fallback: number): number {\n // Shared env parsing helper:\n // - missing/invalid/non-positive => fallback\n // - valid positive integer => parsed value\n if (!value) return fallback;\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n }\n\n private async subscribeWithTimeout(message: QueueMessage<T>, queueName: string): Promise<any> {\n const timeoutMs = this.resolveProcessingTimeoutMs();\n const messageId = message?.messageId || 'unknown';\n\n // Allow an escape hatch: non-positive timeout means run without a soft timeout.\n if (timeoutMs <= 0) {\n return this.subscribe(message);\n }\n\n let timedOut = false;\n let timeoutHandle: NodeJS.Timeout | null = null;\n\n // Main subscriber work promise.\n // If timeout has already fired, suppress rethrow to avoid unhandled rejection noise\n // (the timeout error is already the authoritative failure we track).\n const subscribePromise = this.subscribe(message).catch((error) => {\n if (timedOut) {\n this.logger.error(\n `Subscriber promise rejected after timeout for queue ${queueName} and messageId ${messageId}: ${(error as Error)?.message || String(error)}`,\n (error as Error)?.stack,\n );\n return undefined;\n }\n throw error;\n });\n\n // Timeout promise rejects after timeoutMs with an explicit domain-specific error.\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n timedOut = true;\n reject(new ConsumerProcessingTimeoutError(queueName, messageId, timeoutMs));\n }, timeoutMs);\n });\n\n try {\n // Promise.race settles as soon as the *first* promise settles.\n // - If subscribePromise resolves/rejects first, we use that outcome.\n // - If timeoutPromise rejects first, we fail fast with timeout error.\n // This ensures we mark DB status via normal error handling before broker ack-timeout.\n return await Promise.race([subscribePromise, timeoutPromise]);\n } catch (error) {\n const errorMessage = (error as Error)?.message || String(error);\n this.logger.error(\n `Subscriber execution failed for queue ${queueName} and messageId ${messageId}: ${errorMessage}`,\n (error as Error)?.stack,\n );\n throw error;\n } finally {\n // Always clear timer once race settles to avoid timer leaks.\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\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';\nimport { buildNamespacedQueueName } from './common';\n\nclass ConsumerProcessingTimeoutError extends Error {\n constructor(\n readonly queueName: string,\n readonly messageId: string,\n readonly timeoutMs: number,\n ) {\n super(`Subscriber processing timed out after ${timeoutMs}ms for queue ${queueName} and messageId ${messageId}`);\n this.name = 'ConsumerProcessingTimeoutError';\n }\n}\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 _loggerInstance?: Logger;\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 protected get loggerContext(): string {\n return this.constructor.name;\n }\n\n protected get logger(): Logger {\n if (!this._loggerInstance) {\n this._loggerInstance = new Logger(this.loggerContext);\n }\n return this._loggerInstance;\n }\n\n abstract subscribe(message: QueueMessage<T>);\n\n abstract options(): QueuesModuleOptions;\n\n protected shouldPersistToDatabase(): boolean {\n return this.options().persistToDatabase ?? true;\n }\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 const roleAllowed = ['both', 'subscriber'].includes(this.serviceRole);\n\n if (!roleAllowed) {\n this.logger.log(`RabbitMqSubscriber is disabled because QUEUES_SERVICE_ROLE is \"${this.serviceRole}\". Expected \"both\" or \"subscriber\".`);\n return;\n }\n\n // we will start subscriber only if the current service role is subscriber. \n if (this.url && 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 const namespacedQueueName = buildNamespacedQueueName(queueName);\n try {\n await this.connectAndConsume(namespacedQueueName);\n } catch (err) {\n this.logger.error(`Failed to connect to RabbitMQ for queue ${namespacedQueueName}: ${(err as Error).message}`, (err as Error).stack);\n this.triggerReconnect(namespacedQueueName, 'initial connection failure');\n }\n\n this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(options)} and url: ${this.url}`);\n }\n }\n\n private async connectAndConsume(queueName: string): Promise<void> {\n await this.cleanup();\n this.logger.log(`RabbitMqSubscriber in connectAndConsume for queue: ${queueName} and url: ${this.url}`);\n\n const options = this.options();\n const prefetch = options.prefetch ?? 1;\n if (prefetch < 1) {\n throw new Error(`RabbitMqSubscriber prefetch must be >= 1 for queue ${queueName}`);\n }\n const processingTimeoutMs = this.resolveProcessingTimeoutMs();\n if (processingTimeoutMs > 0) {\n this.logger.log(`RabbitMqSubscriber using processing timeout ${processingTimeoutMs}ms for queue ${queueName}`);\n }\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(prefetch);\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 let message: QueueMessage<T> = null;\n\n try {\n const messageContentString = rawMessage.content.toString();\n message = JSON.parse(messageContentString) as QueueMessage<T>;\n this.logger.debug(`rabbitmq subscriber received message with id: ${message.messageId} for queue ${queueName}`);\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, queueName);\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}`, (error as Error)?.stack);\n\n if (message.currentRetry < message.retryCount) {\n if (this.shouldPersistToDatabase()) {\n await this.updateStatusInDatabase('retrying', message);\n }\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 if (this.shouldPersistToDatabase()) {\n await this.updateStatusInDatabase('failed', message, errorMessage, '');\n }\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, queueName: string): Promise<void> {\n if (this.shouldPersistToDatabase()) {\n await this.updateStatusInDatabase('started', message);\n }\n\n // Capture the results of handling the task.\n const result = await this.subscribeWithTimeout(message, queueName);\n\n // Ack the message. \n channel.ack(rawMessage);\n\n // Persist success output and timing.\n if (this.shouldPersistToDatabase()) {\n await this.updateStatusInDatabase('succeeded', message, '', result ? JSON.stringify(result, null, 2) : '');\n }\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 private resolveProcessingTimeoutMs(): number {\n // Broker-side delivery-ack timeout (ms). If not provided, assume RabbitMQ default\n // behavior used in this project: 30 minutes.\n // Example (RabbitMQ broker):\n // - Broker ack timeout: 30m => 1,800,000ms (QUEUES_RABBITMQ_CONSUMER_ACK_TIMEOUT_MS)\n // - App soft timeout should be slightly lower, e.g. 29m30s => 1,770,000ms\n // (QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS), so application code fails first,\n // records DB state/error, and avoids broker-forced channel close as primary failure signal.\n const brokerTimeoutMs = this.parsePositiveInt(process.env.QUEUES_RABBITMQ_CONSUMER_ACK_TIMEOUT_MS, 30 * 60 * 1000);\n\n // Soft timeout should fire *before* broker timeout so we can fail explicitly,\n // persist status/error, and avoid broker-forced channel closure as primary signal.\n // Keep at least 1s to avoid zero/negative values when broker timeout is very small.\n const defaultSoftTimeoutMs = Math.max(1_000, brokerTimeoutMs - 30_000);\n\n // Final timeout precedence:\n // 1) QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS (if valid positive int)\n // 2) Derived defaultSoftTimeoutMs (broker timeout - 30s)\n return this.parsePositiveInt(process.env.QUEUES_RABBITMQ_SUBSCRIBER_PROCESSING_TIMEOUT_MS, defaultSoftTimeoutMs);\n }\n\n private parsePositiveInt(value: string | undefined, fallback: number): number {\n // Shared env parsing helper:\n // - missing/invalid/non-positive => fallback\n // - valid positive integer => parsed value\n if (!value) return fallback;\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n }\n\n private async subscribeWithTimeout(message: QueueMessage<T>, queueName: string): Promise<any> {\n const timeoutMs = this.resolveProcessingTimeoutMs();\n const messageId = message?.messageId || 'unknown';\n\n // Allow an escape hatch: non-positive timeout means run without a soft timeout.\n if (timeoutMs <= 0) {\n return this.subscribe(message);\n }\n\n let timedOut = false;\n let timeoutHandle: NodeJS.Timeout | null = null;\n\n // Main subscriber work promise.\n // If timeout has already fired, suppress rethrow to avoid unhandled rejection noise\n // (the timeout error is already the authoritative failure we track).\n const subscribePromise = this.subscribe(message).catch((error) => {\n if (timedOut) {\n this.logger.error(\n `Subscriber promise rejected after timeout for queue ${queueName} and messageId ${messageId}: ${(error as Error)?.message || String(error)}`,\n (error as Error)?.stack,\n );\n return undefined;\n }\n throw error;\n });\n\n // Timeout promise rejects after timeoutMs with an explicit domain-specific error.\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n timedOut = true;\n reject(new ConsumerProcessingTimeoutError(queueName, messageId, timeoutMs));\n }, timeoutMs);\n });\n\n try {\n // Promise.race settles as soon as the *first* promise settles.\n // - If subscribePromise resolves/rejects first, we use that outcome.\n // - If timeoutPromise rejects first, we fail fast with timeout error.\n // This ensures we mark DB status via normal error handling before broker ack-timeout.\n return await Promise.race([subscribePromise, timeoutPromise]);\n } catch (error) {\n const errorMessage = (error as Error)?.message || String(error);\n this.logger.error(\n `Subscriber execution failed for queue ${queueName} and messageId ${messageId}: ${errorMessage}`,\n (error as Error)?.stack,\n );\n throw error;\n } finally {\n // Always clear timer once race settles to avoid timer leaks.\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n }\n\n}\n"]}
|