UNPKG

nestjs-temporal-core

Version:

Complete NestJS integration for Temporal.io with auto-discovery, declarative scheduling, enhanced monitoring, and enterprise-ready features

192 lines 8.49 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var TemporalActivityService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.TemporalActivityService = void 0; const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const temporal_metadata_accessor_1 = require("../worker/temporal-metadata.accessor"); const constants_1 = require("../constants"); const logger_1 = require("../utils/logger"); let TemporalActivityService = TemporalActivityService_1 = class TemporalActivityService { constructor(options, discoveryService, metadataAccessor) { this.options = options; this.discoveryService = discoveryService; this.metadataAccessor = metadataAccessor; this.discoveredActivities = new Map(); this.activityHandlers = new Map(); this.logger = (0, logger_1.createLogger)(TemporalActivityService_1.name); } async onModuleInit() { await this.discoverActivities(); this.logActivitySummary(); } async discoverActivities() { const providers = this.discoveryService.getProviders(); let discoveredCount = 0; for (const wrapper of providers) { const { instance, metatype } = wrapper; const targetClass = instance?.constructor || metatype; if (!targetClass || !instance) continue; if (!this.metadataAccessor.isActivity(targetClass)) continue; if (this.options.activityClasses?.length) { if (!this.options.activityClasses.includes(targetClass)) continue; } try { const activityInfo = await this.processActivityClass(instance, targetClass); if (activityInfo) { this.discoveredActivities.set(targetClass.name, activityInfo); discoveredCount++; } } catch (error) { this.logger.error(`Failed to process activity class ${targetClass.name}:`, error.stack); } } this.logger.log(`Discovered ${discoveredCount} activity classes`); } async processActivityClass(instance, targetClass) { const className = targetClass.name; this.logger.debug(`Processing activity class: ${className}`); const validation = this.metadataAccessor.validateActivityClass(targetClass); if (!validation.isValid) { this.logger.warn(`Activity class ${className} has validation issues: ${validation.issues.join(', ')}`); return null; } const activityMethods = this.metadataAccessor.extractActivityMethods(instance); const methodInfos = []; for (const [activityName, handler] of activityMethods.entries()) { this.activityHandlers.set(activityName, handler); const methodName = Object.getOwnPropertyNames(Object.getPrototypeOf(instance)).find((name) => instance[name] === handler); if (methodName) { const method = Object.getPrototypeOf(instance)[methodName]; methodInfos.push({ name: activityName, methodName, options: this.metadataAccessor.getActivityMethodOptions(method), }); } this.logger.debug(`Registered activity: ${className}.${activityName}`); } return { className, instance, targetClass: targetClass, methods: methodInfos, totalMethods: methodInfos.length, }; } getDiscoveredActivities() { return Array.from(this.discoveredActivities.values()); } getActivityByClassName(className) { return this.discoveredActivities.get(className); } getActivityHandlers() { return Object.fromEntries(this.activityHandlers.entries()); } getActivityHandler(activityName) { return this.activityHandlers.get(activityName); } getActivityNames() { return Array.from(this.activityHandlers.keys()); } hasActivity(activityName) { return this.activityHandlers.has(activityName); } getActivityStats() { const activities = this.getDiscoveredActivities(); const totalMethods = activities.reduce((sum, activity) => sum + activity.totalMethods, 0); return { totalClasses: activities.length, totalMethods, classNames: activities.map((a) => a.className), methodNames: this.getActivityNames(), }; } validateConfiguration() { const issues = []; const warnings = []; if (this.discoveredActivities.size === 0) { warnings.push('No activities were discovered. Make sure classes are decorated with @Activity()'); } const methodNames = this.getActivityNames(); const duplicates = methodNames.filter((name, index) => methodNames.indexOf(name) !== index); if (duplicates.length > 0) { issues.push(`Duplicate activity names found: ${duplicates.join(', ')}`); } if (this.options.activityClasses?.length) { const foundClasses = this.getDiscoveredActivities().map((a) => a.targetClass); const missingClasses = this.options.activityClasses.filter((cls) => !foundClasses.includes(cls)); if (missingClasses.length > 0) { warnings.push(`Some specified activity classes were not found: ${missingClasses.map((c) => c.name).join(', ')}`); } } return { isValid: issues.length === 0, issues, warnings, }; } getHealthStatus() { const stats = this.getActivityStats(); const validation = this.validateConfiguration(); let status; if (!validation.isValid) { status = 'unhealthy'; } else if (validation.warnings.length > 0 || stats.totalMethods === 0) { status = 'degraded'; } else { status = 'healthy'; } return { status, activities: { total: stats.totalClasses, registered: stats.totalMethods, }, validation, }; } logActivitySummary() { const stats = this.getActivityStats(); const validation = this.validateConfiguration(); this.logger.log(`Activity discovery completed: ${stats.totalClasses} classes, ${stats.totalMethods} methods`); if (stats.totalClasses > 0) { this.logger.debug(`Activity classes: ${stats.classNames.join(', ')}`); } if (stats.totalMethods > 0) { this.logger.debug(`Activity methods: ${stats.methodNames.join(', ')}`); } if (validation.warnings.length > 0) { validation.warnings.forEach((warning) => this.logger.warn(warning)); } if (validation.issues.length > 0) { validation.issues.forEach((issue) => this.logger.error(issue)); } } }; exports.TemporalActivityService = TemporalActivityService; exports.TemporalActivityService = TemporalActivityService = TemporalActivityService_1 = __decorate([ (0, common_1.Injectable)(), __param(0, (0, common_1.Inject)(constants_1.ACTIVITY_MODULE_OPTIONS)), __metadata("design:paramtypes", [Object, core_1.DiscoveryService, temporal_metadata_accessor_1.TemporalMetadataAccessor]) ], TemporalActivityService); //# sourceMappingURL=temporal-activity.service.js.map