@haku-sci/utils
Version:
utils from haku-sci. Library only
136 lines • 6.82 kB
JavaScript
;
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 TCPService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TCPService = void 0;
const microservices_1 = require("@nestjs/microservices");
const tcp_param_decorator_1 = require("./tcp-param.decorator");
const rxjs_1 = require("rxjs");
const utils = require("../utils");
const consul_1 = require("../microservice/consul");
const common_1 = require("@nestjs/common");
const exceptionFilter_1 = require("../microservice/exceptionFilter");
const constants_1 = require("@nestjs/microservices/constants");
const constants_2 = require("@nestjs/common/constants");
const nestjs_discovery_1 = require("@golevelup/nestjs-discovery");
let TCPService = TCPService_1 = class TCPService {
static async sendMessage(service, action, resource, payload = {}) {
const client = await microservices_1.ClientProxyFactory.create({
transport: microservices_1.Transport.TCP,
options: await consul_1.Consul.getServiceURI(service),
});
try {
payload["sender"] = await utils.microServiceName();
let response$ = await client.send([resource, action].join("/"), payload).pipe((0, rxjs_1.catchError)(err => {
err = err.error || err;
const status = err?.status || common_1.HttpStatus.BAD_REQUEST;
const payload = {
...(typeof err === 'object' ? err : { message: err }),
service,
};
return (0, rxjs_1.throwError)(() => new common_1.HttpException(payload, status));
}));
const watchdogTimeout = parseInt(process.env.WATCHDOG);
if (!isNaN(watchdogTimeout) && watchdogTimeout > 0)
response$ = response$.pipe((0, rxjs_1.timeout)({ first: watchdogTimeout }));
response$ = response$.pipe((0, rxjs_1.defaultIfEmpty)(null));
const result = await (0, rxjs_1.lastValueFrom)(response$);
if (result?.error)
(0, rxjs_1.throwError)(() => new Error(`[${service}] ${result.message}`));
return result;
}
finally {
try {
await client.close();
}
catch (closeError) {
console.error("Error closing client:", closeError.message);
}
}
}
static async registerHakuSciMessageHandlers(app, logger) {
const moduleRef = app.select(nestjs_discovery_1.DiscoveryModule);
const discoveryService = moduleRef.get(nestjs_discovery_1.DiscoveryService, { strict: false });
const controllers = await discoveryService.controllers(() => true);
for (const { instance } of controllers) {
const resource = Reflect.getMetadata(constants_2.PATH_METADATA, instance.constructor).replace("/", "");
const prototype = Object.getPrototypeOf(instance);
for (const propertyName of Object.getOwnPropertyNames(prototype)) {
const method = prototype[propertyName];
if (propertyName === 'constructor' || typeof method !== 'function')
continue;
const action = Reflect.getMetadata(constants_1.PATTERN_METADATA, method)?.[0];
if (action) {
const handler = TCPService_1.wrapHandler(instance, propertyName, logger);
app.serverInstance.addHandler([resource, action].join("/"), handler, false);
}
}
}
TCPService_1.enablePatternRouting(app.serverInstance);
logger.log("HakuSci Message Handlers initialized");
}
static enablePatternRouting(server) {
const handlers = server.messageHandlers;
const paramPatterns = [];
for (const key of handlers.keys()) {
if (!key.includes(':'))
continue;
const paramNames = [];
const regexStr = key.replace(/:([^/]+)/g, (_, name) => {
paramNames.push(name);
return '([^/]+)';
});
paramPatterns.push({ regex: new RegExp(`^${regexStr}$`), paramNames, registeredKey: key });
}
if (paramPatterns.length === 0)
return;
const originalGetHandler = server.getHandlerByPattern.bind(server);
server.getHandlerByPattern = (incomingPattern) => {
const exact = originalGetHandler(incomingPattern);
if (exact)
return exact;
for (const { regex, paramNames, registeredKey } of paramPatterns) {
const match = incomingPattern.match(regex);
if (!match)
continue;
const originalHandler = originalGetHandler(registeredKey);
if (!originalHandler)
continue;
const params = {};
paramNames.forEach((name, i) => { params[name] = match[i + 1]; });
return (data, ctx) => originalHandler({ ...data, params }, ctx);
}
return null;
};
}
static wrapHandler(instance, methodName, logger) {
const prototype = Object.getPrototypeOf(instance);
const tcpParamMeta = Reflect.getMetadata(tcp_param_decorator_1.TCP_PARAM_METADATA_KEY, prototype, methodName) ?? [];
return async function boundHandler(data, context) {
try {
const { params, ...payload } = data ?? {};
const args = [tcpParamMeta.length > 0 ? payload : data];
for (const { index, name } of tcpParamMeta)
args[index] = params?.[name];
return await instance[methodName].apply(instance, args);
}
catch (err) {
const host = {
switchToRpc: () => ({ getContext: () => context }),
getArgByIndex: (i) => (i === 0 ? data : context),
};
return new exceptionFilter_1.AllExceptionsFilter(logger).catch(err, host);
}
};
}
};
exports.TCPService = TCPService;
exports.TCPService = TCPService = TCPService_1 = __decorate([
(0, common_1.Injectable)()
], TCPService);
//# sourceMappingURL=tcp.service.js.map