UNPKG

@carlosbajo/roket-micro

Version:

framework para microservicios con google/pubsub

140 lines (129 loc) 5.44 kB
const _ = require('lodash'); const fs = require('fs'); const fileKey = fs.readFileSync(process.env.GOOGLE_APPLICATION_CREDENTIALS); // eslint-disable-line const { name } = require(`${process.cwd()}/package.json`); // eslint-disable-line const pubsub = require('@google-cloud/pubsub'); const gLogger = require('./google-loggin'); const pubsubClient = pubsub(); const key = JSON.parse(fileKey); const isLocal = key.client_email.includes('local'); const nameTopic = (topic) => { let response; if (isLocal) response = `local.${topic}`; else response = topic; return response; }; module.exports = class Pubsub { constructor(logger) { if (logger) this.logger = logger; } static async createMessageStreamForTopic(topic) { const googleTopic = pubsubClient.topic(topic); const consumerClient = await googleTopic.subscribe(nameTopic(`${name}.${topic}`)); return consumerClient[0]; } async loadSubscription(pubsub, topic) { // eslint-disable-line const tmp = []; const existingTopics = await pubsubClient.getTopics(); const topicNames = existingTopics[0].map(item => item.name); for (const item of pubsub[topic].response) { if (!topicNames.includes(`projects/${process.env.GCLOUD_PROJECT}/topics/${nameTopic(item)}`)) { tmp.push(pubsubClient.createTopic(nameTopic(item))); } } await Promise.all(tmp); if (!topicNames.includes(`projects/${process.env.GCLOUD_PROJECT}/topics/${nameTopic(topic)}`)) await pubsubClient.createTopic(nameTopic(topic)); const googleTopic = pubsubClient.topic(nameTopic(topic)); const consumerClient = await googleTopic.subscribe(nameTopic(`${name}.${topic}`)); return { topic: googleTopic, consumerClient: consumerClient[0] }; } static createMessageResponseObject(body, request) { const messageResponseObject = { errors: [], body }; if (!request.correlation_id) { messageResponseObject.errors.push(`Invalid Request: Request is missing correlation_id. Request is ${request}`); } else { messageResponseObject.correlation_id = request.correlation_id; } if (!request.request_id) { messageResponseObject.errors.push(`Invalid Request: Request is missing request_id. Request is ${request}`); } else { messageResponseObject.request_id = request.request_id; } if (messageResponseObject.errors.length === 0) { delete messageResponseObject.errors; } return messageResponseObject; } writeResponseForRequest(response, request) { let tmp; if (!request.response_topic) { tmp = Promise.reject('Request is missing a response_topic. Request: %j'); } else { const messageObject = pubsub.createMessageResponseObject(response, request); tmp = this.writeMessageToTopic(JSON.stringify(messageObject), request.response_topic); } return tmp; } async writeMessageToTopic(messageString, topic, req) { const log = gLogger(this.logger); let isBoom; const message = JSON.parse(messageString); if (!isBoom) log(topic, _.get(req, 'usr.id', 'undefined'), message); return message; // topic = nameTopic(`${method || 'res'}.${name}.${topic}`); // const googleTopic = pubsubClient.topic(topic); // return new Promise((resolve, reject) => { // if (this.logger) this.logger.info(`Topic: ${topic}, payload: ${messageString}`); // if (_.isObject(messageString)) { // isBoom = messageString.isBoom; // messageString = JSON.stringify(messageString); // } else { // message = JSON.parse(messageString); // isBoom = message.isBoom; // } // googleTopic.publish(messageString).then(res => { // if (!isBoom) log(topic, _.get(req, 'usr.id', 'undefined'), message); // resolve(res[0]); // }).catch(err => reject(err)); // }); } resolve(request, response) { const opt = { autoAck: true }; // es en milisegundos const requestTopic = pubsubClient.topic(nameTopic(request)); const responseTopic = pubsubClient.topic(nameTopic(response)); this.logger.info('subscribe to', nameTopic(`${name}.${response}`)); const consumerResponse = responseTopic.subscribe(nameTopic(`${name}.${response}`), opt); return async (parent, args, ctx) => { if (ctx.jwt.error) return Promise.reject(ctx.jwt.error.output.payload.message); const data = { object: parent, args: args || {}, jwt: ctx.jwt.usrJwt, }; requestTopic.publish(JSON.stringify(data)) .catch((error) => this.logger.error(error)) .then((res) => { this.logger.info(`message sent to ${nameTopic(request)}`, JSON.stringify(args)); this.logger.info(res); }); let consumer = await consumerResponse; consumer = consumer[0]; return new Promise((resolve, reject) => { consumer.on('message', message => { let val = message.data; val = (_.isEmpty(val) ? {} : JSON.parse(val)); if (val.isBoom) { const format = `Request Topic: ${nameTopic(request)}, Response Topic: ${nameTopic(response)}, statusCode: ${val.output.statusCode}, message: ${val.output.payload.message}, Error: ${val.output.payload.error}`; reject(format); } else { resolve(val.payload || val); } }); consumer.on('error', error => reject(error)); }); }; } };