"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.init = init;
exports.add = add;
exports.act = act;
const _ = require("lodash");
const path = require("path");
const rp = require("request-promise");
const fastify = require("fastify");
const common_1 = require("../common");
const log_1 = require("../log");
const service_1 = require("../service");
let logger;
const api = {};
const fast = fastify({ trustProxy: true });
let targetPort = 0;
function init(cfg, callback) {
    logger = new log_1.Log(`msbase_fastify`);
    if (cfg.targetPort)
        targetPort = cfg.targetPort;
    const start = () => {
        if (!cfg.port)
            return;
        try {
            _.forEach(cfg.apipath ? cfg.apipath : ['./build/services/'], common_1.requiredir);
        }
        catch (error) {
            logger.log(error.message);
        }
        logger.log('api initialized');
        let circuitBreakerOpt = { threshold: 3, timeout: 3000, resetTimeout: 3000 };
        if (cfg.circuitBreaker)
            circuitBreakerOpt = { ...circuitBreakerOpt, ...cfg.circuitBreaker };
        fast.register(require('fastify-circuit-breaker'), circuitBreakerOpt);
        fast.register(require('fastify-compress'), { global: false });
        try {
            const route = cfg.routefile ? require(path.resolve(cfg.routefile)) : null;
            if (route)
                route(fast);
        }
        catch (error) {
            logger.log(error.message);
        }
        _.keys(api).length > 0 && fast.register(function (instance, opts, next) {
            instance.route({
                method: 'POST',
                url: '/:cmd/',
                handler: async (request, reply) => {
                    let payload = {};
                    const start = Date.now();
                    const name = request.params.cmd.toLowerCase();
                    const bodyJson = JSON.stringify(request.body);
                    logger.debug(`1-api-${name} args-${bodyJson}`, { method_name: name });
                    try {
                        const action = api[name];
                        if (!action)
                            throw new Error(`${name} does not exist in ${cfg.name}`);
                        payload.result = await action(request.body);
                    }
                    catch (error) {
                        payload.error = error.message;
                    }
                    const hs = Date.now() - start;
                    let spend_time = Math.floor(hs / 50);
                    if (spend_time > 99)
                        spend_time = 99;
                    logger.debug(`2-api-${name} args-${bodyJson} result-${JSON.stringify(payload)} 耗时-${hs}`, { method_name: name, spend_time: spend_time });
                    reply.compress(payload);
                }
            });
            console.log('start ms api route');
            next();
        });
        fast.listen(cfg.port, '0.0.0.0', (err, address) => {
            if (err)
                throw err;
            logger.info(`server listening on ${address}`);
        });
    };
    callback ? callback(start) : start();
}
function add(args, callback) {
    api[args.cmd] = callback;
    console.log(`api '${args.cmd}' success`);
}
async function act(args, isThrowError = false) {
    if (!args.topic || !args.cmd)
        throw new Error('topic or cmd is null');
    if (args.topic)
        args.topic = args.topic.toLowerCase();
    if (args.cmd)
        args.cmd = args.cmd.toLowerCase();
    const args_obj = _.pick(args, ['data', 'context']);
    const body = JSON.stringify(args_obj);
    if (args.topic === service_1.config.name)
        return api[args.cmd]({ ...args_obj });
    const url = `http://service-${args.topic}${targetPort ? (':' + targetPort) : ''}/${args.cmd}/`;
    const start = Date.now();
    let ret = await rp.post(url, { body, gzip: true, forever: true, headers: { 'Content-Type': 'application/json' } })
        .then(body => JSON.parse(body))
        .catch(e => { return { error: e.message }; });
    const hs = Date.now() - start;
    let spend_time = Math.floor(hs / 50);
    if (spend_time > 99)
        spend_time = 99;
    const msg = `act--${url}|${body}|${JSON.stringify(ret)}|${hs}`;
    const opts = { method_name: args.cmd, spend_time: spend_time };
    logger.debug(msg, opts);
    if (ret) {
        if ('error' in ret) {
            logger.error(msg, opts);
            if (isThrowError)
                throw new Error(ret.error);
        }
        if ('result' in ret) {
            ret = ret.result;
        }
    }
    return ret;
}
//# sourceMappingURL=fast.js.map