UNPKG

@ckstack/ck-push-sender

Version:

push sender server module

359 lines (358 loc) 20.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); const _ = __importStar(require("underscore")); const JSON5 = __importStar(require("json5")); const fs = __importStar(require("fs")); const ck_lib_sequelize_1 = require("@ckstack/ck-lib-sequelize"); const ck_lib_models_1 = require("@ckstack/ck-lib-models"); const dk_lib_mqtt_1 = require("@dkpkg/dk-lib-mqtt"); const dk_lib_slack_1 = require("@dkpkg/dk-lib-slack"); const ck_lib_gw_1 = require("@ckstack/ck-lib-gw"); const dk_lib_1 = require("@dkpkg/dk-lib"); const MyConfig_1 = require("../../../MyConfig"); const MyValues_1 = require("../../../MyValues"); class PushMqtt { constructor(delayVendor) { this.delayVendor = delayVendor; if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH && !fs.existsSync(MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH)) { dk_lib_1.CkLogger.errLog2(`not found tls key path for mqtt broker connection. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH}]. process terminate.`, MyValues_1.PROC_LHD.LHD); dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`not found tls key path for mqtt broker connection. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH}]. process terminate.`); return; } if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH && !fs.existsSync(MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH)) { dk_lib_1.CkLogger.errLog2(`not found tls cert path for mqtt broker. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH}]. process terminate.`, MyValues_1.PROC_LHD.LHD); dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`not found tls cert path for mqtt broker. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH}]. process terminate.`); return; } dk_lib_1.CkLogger.infoLog('create MQTT Broker client', MyValues_1.PROC_LHD.LHD); } connect() { return __awaiter(this, void 0, void 0, function* () { const brokerInfo = [ { PROTOCOL: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_PROTOCOL, HOST: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_HOST, PORT: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_PORT, CLIENT_ID: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_CLIENT_ID, KEEP_ALIVE: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_KEEP_ALIVE, RECONNECT_PERIOD: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_RECONNECT_PERIOD, CONNECT_TIMEOUT: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_CONNECT_TIMEOUT, TLS_SELF_SIGNED: MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_SELF_SIGNED, }, ]; if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_USER_ID) { brokerInfo[0].USER_ID = MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_USER_ID; } if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_USER_PASSWORD) { brokerInfo[0].USER_PASSWORD = MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_USER_PASSWORD; } if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH) { brokerInfo[0].TLS_KEY_PATH = MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_KEY_PATH; } if (MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH) { brokerInfo[0].TLS_CERT_PATH = MyConfig_1.conf.HTF_PUSH_VENDOR_MQTT_TLS_CERT_PATH; } dk_lib_mqtt_1.CkMqtt.init(brokerInfo); const connected = yield dk_lib_mqtt_1.CkMqtt.connect(); if (!connected) { dk_lib_1.CkLogger.errLog2(`can't connect to mqtt broker for push. broker info [${JSON5.stringify(brokerInfo)}]. process terminate.`, MyValues_1.PROC_LHD.LHD); yield dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`can't connect to mqtt broker for push. broker info [${JSON5.stringify(brokerInfo)}]. process terminate.`); } }); } validateMessage(_lhd, _msgData) { const lhd = _lhd || `${MyValues_1.PROC_LHD.IP_LHD_HTTP}`; const msgData = _msgData; if (!msgData.yyyymm) { dk_lib_1.CkLogger.warnLog2(`invalid request. no yyyymm. yyyymm [${msgData.yyyymm}]`, lhd); return undefined; } if (!msgData.targetUserId) { msgData.targetUserId = undefined; } if (!msgData.title && !msgData.body && (msgData.data === undefined || _.size(msgData.data) <= 0)) { dk_lib_1.CkLogger.warnLog2(`invalid request. no title [${msgData.title}], body [${msgData.body}], ` + `data [${JSON5.stringify(msgData.data)}]`, lhd); return undefined; } if (!msgData.topic) { dk_lib_1.CkLogger.errLog2(`invalid request. not found publish topic [${msgData.topic}], ` + `msgData [${JSON5.stringify(_msgData)}]`, lhd); return undefined; } msgData.pushVendor = dk_lib_1.CkValue.PUSH_VENDOR_TYPE.MQTT; if (msgData.maxRetryCount && msgData.maxRetryCount > MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT) { dk_lib_1.CkLogger.warnLog2('The maximum number of resends is too large. Force the number of times. ' + `request number [${msgData.maxRetryCount}], force set number [${MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT}]`, lhd); msgData.maxRetryCount = MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT; } if (msgData.maxRetryCount && msgData.maxRetryCount > 9999) { dk_lib_1.CkLogger.warnLog2('The maximum number of resends is too large. Force the static number. ' + `setting number [${MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT}], force set number [9999]`, lhd); msgData.maxRetryCount = 9999; } if (msgData.currentRetryCount === undefined) { msgData.currentRetryCount = 0; } return { msgData, isBroadcast: false }; } getPayload(_lhd, _msgData) { const lhd = _lhd || `${MyValues_1.PROC_LHD.IP_LHD_HTTP}`; const msgData = _msgData; const payload = { data: {} }; if (msgData.title || msgData.body || msgData.imageUrl || msgData.sound) { payload.notification = {}; if (msgData.title) { payload.notification.title = msgData.title; } if (msgData.body) { payload.notification.body = msgData.body; } if (msgData.imageUrl) { payload.notification.imageUrl = msgData.imageUrl; } if (msgData.sound) { payload.notification.sound = msgData.sound; } } if (msgData.badge !== undefined) { payload.badge = msgData.badge; } payload.background = (msgData.isBackground === true); if (msgData.arrivalCb && msgData.arrivalCb.trim()) { payload.data.xpCb = msgData.arrivalCb.trim(); dk_lib_1.CkLogger.debugLog2(`set mqtt push arrival callback url [${payload.data.xpCb}]`, lhd); } else { dk_lib_1.CkLogger.debugLog2(`not set mqtt push arrival callback url. msgData.arrivalCb [${msgData.arrivalCb}]`, lhd); } if (!payload.data.xpTid) { payload.data.xpTid = `${Date.now()}`; } if (!payload.data.xpTm) { payload.data.xpTm = `${Math.floor(Date.now() / 1000)}`; } return payload; } sendPush(_lhd, _payload, _msgData, isBroadCast) { return __awaiter(this, void 0, void 0, function* () { const lhd = _lhd || `${MyValues_1.PROC_LHD.IP_LHD_HTTP}`; const payload = _payload; const msgData = _msgData; let { broadcastId } = msgData; if (msgData.currentRetryCount === undefined || msgData.currentRetryCount === 0 || !broadcastId) { broadcastId = dk_lib_1.CkUtils.getUUIDV5(`${dk_lib_1.CkUtils.getUUID()}-${Date.now()}`); msgData.broadcastId = broadcastId; } let userId = ''; if (msgData.targetUserId !== undefined && msgData.targetUserId.trim() !== '') { userId = msgData.targetUserId.trim(); } else { userId = dk_lib_1.CkCrypto.md5Hash(msgData.topic); } const pushId = ck_lib_gw_1.CommonService.makePushId({ broadcastId, yyyymm: msgData.yyyymm, retryIndex: msgData.currentRetryCount === undefined ? 0 : msgData.currentRetryCount, userId, }, MyConfig_1.conf.HTF_PUSH_ID_JWT_SECRET_KEY); if (isBroadCast) { dk_lib_1.CkLogger.warnLog2(`not support broadcast push on mqtt. topic [${msgData.topic}], payload [${JSON.stringify(payload)}]`, lhd); } const bPushRet = yield this.publishMessage(lhd, payload, msgData, pushId, broadcastId); yield this.upsertPushHistoryToRDBMS(lhd, msgData, bPushRet); }); } publishMessage(lhd, payload, msgData, pushId, broadcastId) { return __awaiter(this, void 0, void 0, function* () { const _payload = payload; if (_payload.data) { dk_lib_1.CkLogger.debugLog2(`change payload.data.xpPushId. from [${_payload.data.xpPushId}], to [${pushId}]`, lhd); _payload.data.xpPushId = pushId; } const _msgData = msgData; if (_msgData.data) { dk_lib_1.CkLogger.debugLog2(`change msgData.data.xpPushId. from [${_msgData.data.xpPushId}], to [${pushId}]`, lhd); _msgData.data.xpPushId = pushId; } _msgData.pushId = pushId; _msgData.broadcastId = broadcastId; if (!dk_lib_mqtt_1.CkMqtt.isConnected(lhd, 0)) { dk_lib_1.CkLogger.errLog2('The mqtt broker did not connected.', lhd); return false; } if (_msgData.data && _payload.data) { _payload.data = Object.assign(Object.assign({}, _msgData.data), _payload.data); } const pubMsg = JSON.stringify(_payload); dk_lib_1.CkLogger.debugLog2(`publish message [${pubMsg}]`, lhd); dk_lib_1.CkLogger.infoLog2(`<< try send mqtt publish to topic [${_msgData.topic}]`, lhd); const startTm = Date.now(); const mqSendRet = yield dk_lib_mqtt_1.CkMqtt.sendMessage(lhd, _msgData.topic, pubMsg); dk_lib_1.CkLogger.printElapsedLog2(lhd, startTm, 'send mqtt push', MyConfig_1.conf.HTF_PUSH_ELAPSED_MILLI_SEC); if (!mqSendRet) { dk_lib_1.CkLogger.errLog2(`>> failed send mqtt publish to topic [${_msgData.topic}], ` + `message [${pubMsg}]`, lhd); return false; } dk_lib_1.CkLogger.infoLog2(`>> success send mqtt publish to topic [${_msgData.topic}]`, lhd); return true; }); } upsertPushHistoryToRDBMS(lhd, msgData, pusResult) { var _a, e_1, _b, _c; return __awaiter(this, void 0, void 0, function* () { const rdb = ck_lib_sequelize_1.CkSequelize.getSequelize2(lhd, 0); if (!rdb) { dk_lib_1.CkLogger.errLog2("can't start transaction", lhd); return false; } const transaction = yield rdb.transaction(); dk_lib_1.CkLogger.debugLog2('start transaction', lhd); const delayedMessages = []; const now = new Date(); const nowMilliSec = now.getTime(); const nowSec = Math.floor(nowMilliSec / 1000); const newData = new ck_lib_models_1.TbFcmHistoryTmp(); newData.rid = dk_lib_1.CkUtils.getUUIDV5(`${dk_lib_1.CkUtils.getUUID()}-${Date.now()}`); newData.yyyymm = msgData.yyyymm; newData.retry_index = (msgData.currentRetryCount === undefined ? 0 : msgData.currentRetryCount); if (msgData.targetUserId !== undefined && msgData.targetUserId.trim() !== '') { newData.user_id = msgData.targetUserId.trim(); } else { newData.user_id = dk_lib_1.CkCrypto.md5Hash(msgData.topic); } newData.fcm_msg_id = ''; newData.fcm_send_flag = pusResult ? dk_lib_1.CkValue.PUSH_SEND_RESULT.SUCCESS : dk_lib_1.CkValue.PUSH_SEND_RESULT.FAIL; newData.fcm_err_code = ''; newData.fcm_err_msg = ''; if (MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT > 0) { newData.arrival_flag = dk_lib_1.CkValue.PUSH_ALLIVAL.NO; newData.read_flag = dk_lib_1.CkValue.PUSH_READ.NO; } else { newData.arrival_flag = dk_lib_1.CkValue.PUSH_ALLIVAL.UNKNOWN; newData.read_flag = dk_lib_1.CkValue.PUSH_READ.UNKNOWN; } newData.limit_retry_count = (msgData.maxRetryCount === undefined ? 0 : msgData.maxRetryCount); newData.fcm_msg = Object.assign({}, msgData); if (newData.fcm_msg.currentRetryCount === undefined) { newData.fcm_msg.currentRetryCount = 0; } if (newData.fcm_msg.maxRetryCount === undefined) { newData.fcm_msg.maxRetryCount = 0; } newData.broadcast_id = msgData.broadcastId || dk_lib_1.CkUtils.getUUIDV5(`${dk_lib_1.CkUtils.getUUID()}-${Date.now()}`); newData.extra = {}; newData.push_vendor = dk_lib_1.CkValue.PUSH_VENDOR_TYPE.MQTT; newData.client_id = ''; newData.c_date = new Date(nowSec * 1000); newData.u_date = new Date(nowSec * 1000); const savedData = yield ck_lib_sequelize_1.DatabaseService.createData(lhd, newData, transaction); if (typeof savedData === 'string') { yield transaction.rollback(); dk_lib_1.CkLogger.debugLog2('rollback transaction', lhd); dk_lib_1.CkLogger.errLog2(`can't save mqtt broker send history. pushId [${msgData.pushId}], targetUserId [${msgData.targetUserId}], currentRetryCount [${msgData.currentRetryCount}]. data [${JSON5.stringify(newData)}]`, lhd); return false; } dk_lib_1.CkLogger.infoLog2(`insert mqtt broker push message history DB. rid [${newData.rid}], yyyymm [${newData.yyyymm}], retry index [${newData.retry_index}], user id [${newData.user_id}]`, lhd); if (newData.fcm_send_flag === dk_lib_1.CkValue.PUSH_SEND_RESULT.SUCCESS && (newData.fcm_msg.maxRetryCount > newData.fcm_msg.currentRetryCount)) { delayedMessages.push(JSON5.stringify(newData.fcm_msg)); } else { dk_lib_1.CkLogger.infoLog2(`not use push message send retry. fcm send result [${newData.fcm_send_flag}] is not success or limited max retry count, maxRetryCount [${newData.fcm_msg.maxRetryCount}], currentRetryCount [${newData.fcm_msg.currentRetryCount}]`, lhd); } yield transaction.commit(); dk_lib_1.CkLogger.debugLog2('commit transaction', lhd); if (MyConfig_1.conf.HTF_PUSH_SEND_MAX_RETRY_COUNT > 0) { if (!this.delayVendor) { dk_lib_1.CkLogger.errLog2('The delayed queue for retry was not created normally.', lhd); } else { if (delayedMessages.length > 10) { const messageParts = []; let idx = 0; for (const retryMsg of delayedMessages) { if (idx % 10 === 0) { messageParts.push([]); } const partIdx = Math.floor(idx / 10); messageParts[partIdx].push(retryMsg); idx += 1; } try { for (var _d = true, messageParts_1 = __asyncValues(messageParts), messageParts_1_1; messageParts_1_1 = yield messageParts_1.next(), _a = messageParts_1_1.done, !_a;) { _c = messageParts_1_1.value; _d = false; try { const msgPart = _c; yield this.delayVendor.pushMulti(lhd, msgPart); } finally { _d = true; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = messageParts_1.return)) yield _b.call(messageParts_1); } finally { if (e_1) throw e_1.error; } } } else if (delayedMessages.length === 1) { yield this.delayVendor.pushOne(lhd, delayedMessages[0]); } else if (delayedMessages.length > 1 && delayedMessages.length <= 10) { yield this.delayVendor.pushMulti(lhd, delayedMessages); } } } return true; }); } } exports.default = PushMqtt;