'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _winston = require('winston');

var _winston2 = _interopRequireDefault(_winston);

var _ms = require('ms');

var _ms2 = _interopRequireDefault(_ms);

var _bluebird = require('bluebird');

var _bluebird2 = _interopRequireDefault(_bluebird);

var _lodash = require('lodash');

var _helpers = require('../database/helpers');

var _helpers2 = _interopRequireDefault(_helpers);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new _bluebird2.default(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return _bluebird2.default.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

const LOGS_FLUSH_INTERVAL = (0, _ms2.default)('2s');
const LOGS_CHUNK_SIZE = 1000;

class DbTransport extends _winston2.default.Transport {
  constructor(opts) {
    var _this;

    _this = super(opts);
    this.flushPromise = null;
    this.batches = [];
    this.doFlush = _asyncToGenerator(function* () {
      const batch = _this.batches.shift();

      try {
        if (!batch || !batch.length) {
          return;
        }

        const knex = yield _this.db.get();
        yield knex.batchInsert('logs', batch, LOGS_CHUNK_SIZE).then();
      } catch (err) {
        // We put the logs back on the queue in position 1
        // so that the next call will insert them in the right order
        // This works since `batchInsert` wraps the op in a transaction
        _this.batches.unshift(batch);
      }
    });
    this.flush = _asyncToGenerator(function* () {
      if (_this.flushPromise) {
        return; // Previous flush is not done running
      }

      _this.flushPromise = _this.doFlush();

      yield _this.flushPromise;
      _this.flushPromise = null;
    });
    this.name = 'DBLogger';
    this.db = opts.db;

    opts.janitor.add({
      table: 'logs',
      ttl: opts.ttl
    });

    this.flushInterval = setInterval(this.flush, LOGS_FLUSH_INTERVAL);
  }

  log(level, message, meta, callback) {
    if (!(0, _lodash.isEmpty)(meta)) {
      message += ` (meta=${JSON.stringify(meta)})`;
    }

    this.db.get().then(knex => {
      const row = {
        level,
        message,
        created_on: (0, _helpers2.default)(knex).date.format(new Date())
      };

      if (this.batches.length) {
        this.batches[this.batches.length - 1].push(row);
      } else {
        this.batches.push([row]);
      }
      this.emit('logged');
      callback(null, true);
    }).catch(err => {
      callback(err, null);
    });
  }

  static _query(db, limit = null, order = 'desc') {
    return _asyncToGenerator(function* () {
      const knex = yield db.get();
      let q = knex('logs').select('created_on as timestamp', 'level', 'message').orderBy('created_on', order);
      if (limit) {
        q = q.limit(limit);
      }
      return q.then();
    })();
  }
}
exports.default = DbTransport;
//# sourceMappingURL=db-transport.js.map