@ckstack/ck-push-sender
Version:
push sender server module
376 lines (375 loc) • 21.2 kB
JavaScript
;
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 aws_iot_device_sdk_1 = require("aws-iot-device-sdk");
const bluebird_1 = require("bluebird");
const ck_lib_sequelize_1 = require("@ckstack/ck-lib-sequelize");
const ck_lib_models_1 = require("@ckstack/ck-lib-models");
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 PushAwsIot {
constructor(delayVendor) {
this.delayVendor = delayVendor;
if (!fs.existsSync(MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_PRIVATE_KEY_FILE_PATH)) {
dk_lib_1.CkLogger.errLog2(`not found private key for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_PRIVATE_KEY_FILE_PATH}]. process terminate.`, MyValues_1.PROC_LHD.LHD);
dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`not found private key for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_PRIVATE_KEY_FILE_PATH}]. process terminate.`);
return;
}
if (!fs.existsSync(MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_CERT_FILE_PATH)) {
dk_lib_1.CkLogger.errLog2(`not found client certificate for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_CERT_FILE_PATH}]. process terminate.`, MyValues_1.PROC_LHD.LHD);
dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`not found client certificate for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_CERT_FILE_PATH}]. process terminate.`);
return;
}
if (!fs.existsSync(MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CACERT_FILE_PATH)) {
dk_lib_1.CkLogger.errLog2(`not found ca certificate for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CACERT_FILE_PATH}]. process terminate.`, MyValues_1.PROC_LHD.LHD);
dk_lib_slack_1.CkSlack.sendMessageServerStartFailAndProcessKill(`not found ca certificate for aws iot. file path [${MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CACERT_FILE_PATH}]. process terminate.`);
return;
}
dk_lib_1.CkLogger.infoLog('create AWS IoT MQTT Broker client', MyValues_1.PROC_LHD.LHD);
}
connect() {
return __awaiter(this, void 0, void 0, function* () {
const opts = {
keyPath: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_PRIVATE_KEY_FILE_PATH,
certPath: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLI_CERT_FILE_PATH,
caPath: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CACERT_FILE_PATH,
clientId: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_CLIENT_ID,
region: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_REGION,
baseReconnectTimeMs: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_RECONNECT_MILLI_SEC,
keepalive: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_KEEP_ALIVE_SEC,
protocol: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_PROTOCOL,
port: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_PORT,
host: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_HOST,
debug: MyConfig_1.conf.HTF_PUSH_VENDOR_AWS_MQTT_DEBUG,
};
dk_lib_1.CkLogger.infoLog(`try connect aws mqtt broker. host [${opts.host}], port [${opts.port}], `
+ `clientId [${opts.clientId}]`, MyValues_1.PROC_LHD.LHD);
this.broker = new aws_iot_device_sdk_1.device(opts);
this.broker.on('connect', this.handlerConnect.bind(this));
this.broker.on('close', this.handlerClose.bind(this));
this.broker.on('reconnect', this.handlerReconnect.bind(this));
this.broker.on('offline', this.handlerOffline.bind(this));
this.broker.on('error', this.handlerError.bind(this));
});
}
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.AWS_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 aws mqtt push arrival callback url [${payload.data.xpCb}]`, lhd);
}
else {
dk_lib_1.CkLogger.debugLog2(`not set aws 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 aws-iot 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* () {
return new bluebird_1.Promise((resolve) => {
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 (!this.broker) {
dk_lib_1.CkLogger.errLog2('The aws-iot mqtt broker was not created normally.', lhd);
resolve(false);
return;
}
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 aws-iot mqtt publish to topic [${_msgData.topic}]`, lhd);
const startTm = Date.now();
this.broker.publish(_msgData.topic, pubMsg, undefined, (err) => {
dk_lib_1.CkLogger.printElapsedLog2(lhd, startTm, 'send aws-iot mqtt push', MyConfig_1.conf.HTF_PUSH_ELAPSED_MILLI_SEC);
if (err) {
dk_lib_1.CkLogger.errLog2(`>> failed send aws-iot mqtt publish to topic [${_msgData.topic}], `
+ `message [${pubMsg}], err [${err.toString()}]`, lhd);
resolve(false);
return;
}
dk_lib_1.CkLogger.infoLog2(`>> success send aws-iot mqtt publish to topic [${_msgData.topic}]`, lhd);
resolve(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.AWS_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 aws iot send history. pushId [${msgData.pushId}], targetUserId [${msgData.targetUserId}], currentRetryCount [${msgData.currentRetryCount}]. data [${JSON5.stringify(newData)}]`, lhd);
return false;
}
dk_lib_1.CkLogger.infoLog2(`insert aws iot 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;
});
}
handlerConnect() {
dk_lib_1.CkLogger.infoLog('connected aws iot mqtt broker', MyValues_1.PROC_LHD.LHD);
}
handlerClose() {
dk_lib_1.CkLogger.warnLog('closed aws iot mqtt broker', MyValues_1.PROC_LHD.LHD);
}
handlerReconnect() {
dk_lib_1.CkLogger.infoLog('reconnect aws iot mqtt broker', MyValues_1.PROC_LHD.LHD);
}
handlerOffline() {
dk_lib_1.CkLogger.infoLog('offline aws iot mqtt broker', MyValues_1.PROC_LHD.LHD);
}
handlerError(err) {
dk_lib_1.CkLogger.errLog(`error aws iot mqtt broker. error [${err.toString()}]`, MyValues_1.PROC_LHD.LHD);
}
}
exports.default = PushAwsIot;