UNPKG

@escueladigital/micro

Version:

Microservice manager for nodejs with kafka

155 lines (139 loc) 4.4 kB
/* eslint-disable no-console */ /* eslint-disable class-methods-use-this */ /** * Validaciones : * 1.- Falta validar que cuando este en local o produccion no se solicite el sasl * 2.- Se tiene que eliminar el archivo pubsub.js ya no es necesario * 3.- Falta implementar error reporter * 4.- Falta implementar trace * 5.- Implementar Circuit Breaker * 6.- Control de fallos. */ const { Kafka } = require('kafkajs') const { name } = require(`${process.cwd()}/package.json`) const uuidPackage = require('uuid') const chalk = require('chalk') const environment = process.env.NODE_ENV class Pubsub { constructor(logger) { this.logger = logger const host = process.env.KAFKA_ADDRESS || '192.168.8.14' const sasl = environment === 'local' ? null : { mechanism: 'plain', // scram-sha-256 or scram-sha-512 username: process.env.KAFKA_USER, password: process.env.KAFKA_PASSWORD, } this.kafka = new Kafka({ brokers: [`${host}:9092`], clientId: `${name}_client${environment}3`, sasl, }) this.consumer = this.kafka.consumer({ groupId: `${name}-consumer-${environment}2`, }) this.parasite = this.kafka.consumer({ groupId: `${name}-consumer-${environment}-parasite3`, }) this.producer = this.kafka.producer() this.admin = this.kafka.admin() this.reqResources = {} } nameTopic(topic) { return `${process.env.NODE_ENV}.${topic}` } async getMicroTopics(deleteTopics = []) { const { topics } = await this.admin.fetchTopicMetadata() let allTopics = [] for (let i = 0; i < deleteTopics.length; i += 1) { const microtopic = topics.filter(topic => topic.name.includes(`micro.${deleteTopics[i]}.`)) allTopics = allTopics.concat(microtopic) } return allTopics } timeOut(promise, TIME) { setTimeout(() => promise.reject(new Error('Micro no contesto')), TIME) } async openConnection() { await this.consumer.connect() await this.admin.connect() await this.producer.connect() } async rpc(topic, args) { const envTopic = this.nameTopic(topic) return new Promise(async (resolve, reject) => { const id = uuidPackage() try { const data = { uuid: id, arg: args || {} } this.reqResources[id] = { resolve, reject } await this.writeMessageToMicro(JSON.stringify(data), envTopic) setTimeout( () => reject(new Error('RPC no contesto, revisar topic name')), process.env.MICRO_TIME_OUT || 3000 ) } catch (e) { delete this.reqResources[id] reject(e.toString()) } }) } async closeConnection() { await this.producer.disconnect() await this.admin.disconnect() await this.consumer.disconnect() } // Carga las subscripciones de todos los topicos asociados. async loadSubscription(topic) { await this.consumer.subscribe({ topic: topic.req }) } async setUpProject(topics) { const proccesedTopics = topics.map(topic => ({ topic: topic.req })) const proccesedTopicsRes = topics.map(topic => ({ topic: topic.res })) const proccesedTopicsMicro = topics.map(topic => ({ topic: topic.micro })) const resulted = proccesedTopics.concat(proccesedTopicsRes) const withMicro = resulted.concat(proccesedTopicsMicro) this.logger.info(chalk.bgGreen(chalk.black('*** CREATING TOPICS ***'))) for (let i = 0; i < withMicro.length; i += 1) { const topic = withMicro[i] try { await this.admin.createTopics({ topics: [topic] }) } catch (e) { console.log('e') } } this.logger.info(chalk.bgGreen(chalk.black('*** CREATING TOPICS - END ***'))) } async writeMessageToMicro(value, topic) { this.logger.info(topic) this.logger.info(value) try { await this.producer.send({ topic, messages: [{ value, headers: { responseKind: 'micro' } }], }) } catch (e) { console.log(e) } } async writeMessageToTopic(value, topic, responseKind = 'none') { try { await this.producer.send({ topic: this.nameTopic(topic), messages: [ { value, headers: { responseKind, }, }, ], }) } catch (e) { console.log(e) } } } module.exports = Pubsub