webhook-sender.js 2.92 KB
const MODULE_NAME = 'WEBHOOK-SENDER';

const axios = require('axios');
const moment = require('moment');
const fs = require('fs');
const path = require('path');
const stringify = require('json-stringify-pretty-compact');
const config = require('komodo-sdk/config');
const logger = require('tektrans-logger');

const DEFAULT_MAX_RETRY = 10;
const DEFAULT_SLEEP_BEFORE_RETRY_MS = 10 * 1000;

const maxRetry = Number(config.webhook && config.webhook.max_retry)
    || DEFAULT_MAX_RETRY;
const sleepBeforeRetryMs = Number(config.webhook && config.webhook.sleep_before_retry_ms)
    || DEFAULT_SLEEP_BEFORE_RETRY_MS;

const baseDumpDir = path.join('dump', 'webhook-sender');
if (!fs.existsSync(baseDumpDir)) {
    fs.mkdirSync(baseDumpDir, { recursive: true });
}
const lastDumpFileName = path.join(baseDumpDir, 'last.json');

const sleepMs = (ms) => new Promise((resolve) => {
    setTimeout(() => {
        resolve();
    }, ms);
});

const dumper = async (xid, webhookType, body) => {
    if (!config.webhook || !config.webhook.dump) {
        return;
    }

    try {
        const filename = [moment().format('YYYYMMDD-HHmmssSSS'), xid].join('_');
        await fs.promises.writeFile(
            path.join(baseDumpDir, `${filename}.json`),
            stringify({ webhookType, body }),
        );

        await fs.promises.writeFile(
            lastDumpFileName,
            stringify({ webhookType, body }),
        );
    } catch (e) {
        logger.warn(`${MODULE_NAME} D3EF00D9: Exception on dumper`, {
            xid,
            eCode: e.code,
            eMessage: e.message || e.toString(),
        });
    }
};

const sender = async (xid, webhookType, body, retry) => {
    if (!config.webhook || !config.webhook.url) {
        return;
    }

    try {
        logger.verbose(`${MODULE_NAME} 2CA59ED3: Sending webhook`, {
            xid,
            webhookType,
            partner: config.webhook.url,
            trxId: body.transaction_id,
            request_id: body.request_id,
        });

        await axios.post(config.listener.partner.webhook, {
            webhookType,
            body,
        });

        await dumper(xid, webhookType, body);

        logger.verbose(`${MODULE_NAME} 50BE8D98: Webhook sent`, {
            xid,
            webhookType,
            partner: config.listener.partner.webhook,
        });
    } catch (e) {
        logger.warn(`${MODULE_NAME} ECC37ECA: Exception on calling webhook`, {
            xid,
            httpStatusCode: e.response && e.response.status,
            eCode: e.code,
            eMessage: e.message || e.toString(),
            retried: retry || 0,
            maxRetry,
        });

        if ((retry || 0) >= maxRetry) {
            logger.warn(`${MODULE_NAME} 4A60B406: Max retry exceeded`, {
                xid,
            });

            return;
        }

        await sleepMs(sleepBeforeRetryMs);
        await sender(xid, webhookType, body, (retry || 0) + 1);
    }
};
module.exports = sender;