nestjs-temporal-core
Version:
Complete NestJS integration for Temporal.io with auto-discovery, declarative scheduling, enhanced monitoring, and enterprise-ready features
191 lines • 7.94 kB
JavaScript
"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 TemporalDiscoveryService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemporalDiscoveryService = void 0;
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const constants_1 = require("../constants");
const logger_1 = require("../utils/logger");
let TemporalDiscoveryService = TemporalDiscoveryService_1 = class TemporalDiscoveryService {
constructor(discoveryService, metadataScanner) {
this.discoveryService = discoveryService;
this.metadataScanner = metadataScanner;
this.logger = (0, logger_1.createLogger)(TemporalDiscoveryService_1.name);
this.scheduledWorkflows = new Map();
this.signals = new Map();
this.queries = new Map();
}
async onModuleInit() {
await this.discoverComponents();
}
async discoverComponents() {
const allWrappers = [
...this.discoveryService.getProviders(),
...this.discoveryService.getControllers(),
];
for (const wrapper of allWrappers) {
await this.processWrapper(wrapper);
}
this.logDiscoveryResults();
}
async processWrapper(wrapper) {
const { instance, metatype } = wrapper;
if (!instance || !metatype) {
return;
}
this.logger.debug(`Processing wrapper: ${metatype.name}`);
await this.discoverMethods(instance);
}
async discoverMethods(instance) {
const prototype = Object.getPrototypeOf(instance);
const methodNames = this.metadataScanner
.scanFromPrototype(instance, prototype, (methodName) => methodName !== 'constructor' ? methodName : null)
.filter((methodName) => Boolean(methodName));
for (const methodName of methodNames) {
const method = prototype[methodName];
if (!method || typeof method !== 'function') {
continue;
}
this.categorizeMethod(instance, methodName, method);
}
}
categorizeMethod(instance, methodName, method) {
const boundMethod = method.bind(instance);
const scheduleMetadata = Reflect.getMetadata(constants_1.TEMPORAL_SCHEDULED_WORKFLOW, method);
if (scheduleMetadata) {
const scheduledInfo = this.createScheduledMethodInfo(methodName, scheduleMetadata, boundMethod, instance);
this.scheduledWorkflows.set(scheduleMetadata.scheduleId, scheduledInfo);
}
const signalMetadata = Reflect.getMetadata(constants_1.TEMPORAL_SIGNAL_METHOD, method);
if (signalMetadata) {
const signalInfo = this.createSignalMethodInfo(methodName, signalMetadata, boundMethod);
this.signals.set(signalMetadata.name || methodName, signalInfo);
}
const queryMetadata = Reflect.getMetadata(constants_1.TEMPORAL_QUERY_METHOD, method);
if (queryMetadata) {
const queryInfo = this.createQueryMethodInfo(methodName, queryMetadata, boundMethod);
this.queries.set(queryMetadata.name || methodName, queryInfo);
}
}
createScheduledMethodInfo(methodName, scheduleMetadata, boundMethod, instance) {
const metadata = scheduleMetadata;
return {
methodName,
workflowName: metadata.workflowName || methodName,
scheduleOptions: metadata,
workflowOptions: {
taskQueue: metadata.taskQueue || 'default',
},
handler: boundMethod,
controllerInfo: {
name: instance.constructor.name,
instance,
},
};
}
createSignalMethodInfo(methodName, metadata, boundMethod) {
const signalMetadata = metadata;
return {
methodName,
signalName: signalMetadata.name || methodName,
options: signalMetadata,
handler: boundMethod,
};
}
createQueryMethodInfo(methodName, metadata, boundMethod) {
const queryMetadata = metadata;
return {
methodName,
queryName: queryMetadata.name || methodName,
options: queryMetadata,
handler: boundMethod,
};
}
getScheduledWorkflows() {
return Array.from(this.scheduledWorkflows.values());
}
getScheduledWorkflow(scheduleId) {
return this.scheduledWorkflows.get(scheduleId);
}
getScheduleIds() {
return Array.from(this.scheduledWorkflows.keys());
}
hasSchedule(scheduleId) {
return this.scheduledWorkflows.has(scheduleId);
}
getSignals() {
return Array.from(this.signals.values());
}
getSignal(signalName) {
return this.signals.get(signalName);
}
getQueries() {
return Array.from(this.queries.values());
}
getQuery(queryName) {
return this.queries.get(queryName);
}
getStats() {
return {
controllers: 0,
methods: 0,
scheduled: this.scheduledWorkflows.size,
signals: this.signals.size,
queries: this.queries.size,
};
}
getHealthStatus() {
const stats = this.getStats();
const status = stats.scheduled > 0 || stats.signals > 0 || stats.queries > 0 ? 'healthy' : 'degraded';
return {
status,
discoveredItems: stats,
lastDiscovery: new Date(),
};
}
getWorkflowControllers() {
this.logger.warn('getWorkflowControllers() is deprecated - workflow controllers are no longer supported');
return [];
}
getWorkflowMethod(_workflowName) {
this.logger.warn('getWorkflowMethod() is deprecated - workflow methods are no longer supported');
return undefined;
}
getWorkflowNames() {
this.logger.warn('getWorkflowNames() is deprecated - workflow names are no longer supported');
return [];
}
hasWorkflow(_workflowName) {
this.logger.warn('hasWorkflow() is deprecated - workflow existence check is no longer supported');
return false;
}
logDiscoveryResults() {
const stats = this.getStats();
this.logger.log(`Discovery completed: ${stats.scheduled} scheduled workflows, ${stats.signals} signals, ${stats.queries} queries`);
if (stats.scheduled > 0) {
this.logger.debug(`Discovered scheduled workflows: ${Array.from(this.scheduledWorkflows.keys()).join(', ')}`);
}
if (stats.signals > 0) {
this.logger.debug(`Discovered signals: ${Array.from(this.signals.keys()).join(', ')}`);
}
if (stats.queries > 0) {
this.logger.debug(`Discovered queries: ${Array.from(this.queries.keys()).join(', ')}`);
}
}
};
exports.TemporalDiscoveryService = TemporalDiscoveryService;
exports.TemporalDiscoveryService = TemporalDiscoveryService = TemporalDiscoveryService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [core_1.DiscoveryService,
core_1.MetadataScanner])
], TemporalDiscoveryService);
//# sourceMappingURL=temporal-discovery.service.js.map