2016-11-04 09:03:13 +01:00
|
|
|
/* eslint camelcase: "off" */
|
2020-04-14 22:29:11 +02:00
|
|
|
|
2016-11-04 09:03:13 +01:00
|
|
|
'use strict';
|
|
|
|
|
2019-08-04 11:15:40 +02:00
|
|
|
const metricsHelper = require('../metrics-helper');
|
2019-08-04 11:10:51 +02:00
|
|
|
const { DB_TIME } = require('../events');
|
|
|
|
|
2017-06-28 10:17:14 +02:00
|
|
|
const COLUMNS = [
|
|
|
|
'app_name',
|
|
|
|
'instance_id',
|
2017-06-28 23:13:29 +02:00
|
|
|
'sdk_version',
|
2017-06-28 10:17:14 +02:00
|
|
|
'client_ip',
|
|
|
|
'last_seen',
|
|
|
|
'created_at',
|
|
|
|
];
|
2016-11-04 09:03:13 +01:00
|
|
|
const TABLE = 'client_instances';
|
|
|
|
|
2017-09-07 22:52:24 +02:00
|
|
|
const ONE_DAY = 24 * 61 * 60 * 1000;
|
|
|
|
|
2017-06-28 10:17:14 +02:00
|
|
|
const mapRow = row => ({
|
2016-11-05 14:08:47 +01:00
|
|
|
appName: row.app_name,
|
|
|
|
instanceId: row.instance_id,
|
2017-06-28 23:13:29 +02:00
|
|
|
sdkVersion: row.sdk_version,
|
2016-11-05 14:08:47 +01:00
|
|
|
clientIp: row.client_ip,
|
|
|
|
lastSeen: row.last_seen,
|
|
|
|
createdAt: row.created_at,
|
|
|
|
});
|
|
|
|
|
2021-03-04 12:54:13 +01:00
|
|
|
const mapToDb = client => ({
|
|
|
|
app_name: client.appName,
|
|
|
|
instance_id: client.instanceId,
|
|
|
|
sdk_version: client.sdkVersion || '',
|
|
|
|
client_ip: client.clientIp,
|
|
|
|
last_seen: client.lastSeen || 'now()',
|
|
|
|
});
|
|
|
|
|
2016-11-05 14:08:47 +01:00
|
|
|
class ClientInstanceStore {
|
2019-08-04 11:10:51 +02:00
|
|
|
constructor(db, eventBus, getLogger) {
|
2016-11-05 14:08:47 +01:00
|
|
|
this.db = db;
|
2019-08-04 11:10:51 +02:00
|
|
|
this.eventBus = eventBus;
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger = getLogger('client-instance-store.js');
|
2020-12-16 14:56:48 +01:00
|
|
|
this.metricTimer = action =>
|
2020-09-18 09:05:09 +02:00
|
|
|
metricsHelper.wrapTimer(eventBus, DB_TIME, {
|
|
|
|
store: 'instance',
|
|
|
|
action,
|
|
|
|
});
|
2017-09-07 22:52:24 +02:00
|
|
|
const clearer = () => this._removeInstancesOlderThanTwoDays();
|
|
|
|
setTimeout(clearer, 10).unref();
|
2020-12-16 14:49:11 +01:00
|
|
|
this.timer = setInterval(clearer, ONE_DAY).unref();
|
2016-11-28 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2020-09-18 09:05:09 +02:00
|
|
|
async _removeInstancesOlderThanTwoDays() {
|
|
|
|
const rows = await this.db(TABLE)
|
2017-06-28 10:17:14 +02:00
|
|
|
.whereRaw("created_at < now() - interval '2 days'")
|
2020-09-18 09:05:09 +02:00
|
|
|
.del();
|
|
|
|
|
|
|
|
if (rows > 0) {
|
|
|
|
this.logger.debug(`Deleted ${rows} instances`);
|
|
|
|
}
|
2016-11-05 14:08:47 +01:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:54:13 +01:00
|
|
|
async bulkUpsert(instances) {
|
|
|
|
const rows = instances.map(mapToDb);
|
2016-11-05 14:08:47 +01:00
|
|
|
return this.db(TABLE)
|
2021-03-04 12:54:13 +01:00
|
|
|
.insert(rows)
|
|
|
|
.onConflict(['app_name', 'instance_id'])
|
|
|
|
.merge();
|
2016-11-04 09:03:13 +01:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:54:13 +01:00
|
|
|
async exists({ appName, instanceId }) {
|
|
|
|
const result = await this.db.raw(
|
|
|
|
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE app_name = ? AND instance_id = ?) AS present`,
|
|
|
|
[appName, instanceId],
|
|
|
|
);
|
|
|
|
const { present } = result.rows[0];
|
|
|
|
return present;
|
2016-11-04 09:03:13 +01:00
|
|
|
}
|
|
|
|
|
2020-09-18 09:05:09 +02:00
|
|
|
async insert(details) {
|
2020-12-16 14:56:48 +01:00
|
|
|
const stopTimer = this.metricTimer('insert');
|
2020-09-18 09:05:09 +02:00
|
|
|
|
2021-03-04 12:54:13 +01:00
|
|
|
const item = await this.db(TABLE)
|
|
|
|
.insert(mapToDb(details))
|
|
|
|
.onConflict(['app_name', 'instance_id'])
|
|
|
|
.merge();
|
2020-09-18 09:05:09 +02:00
|
|
|
|
|
|
|
stopTimer();
|
|
|
|
|
|
|
|
return item;
|
2016-11-04 09:03:13 +01:00
|
|
|
}
|
|
|
|
|
2020-09-18 09:05:09 +02:00
|
|
|
async getAll() {
|
2020-12-16 14:56:48 +01:00
|
|
|
const stopTimer = this.metricTimer('getAll');
|
2020-09-18 09:05:09 +02:00
|
|
|
|
|
|
|
const rows = await this.db
|
2016-11-04 09:03:13 +01:00
|
|
|
.select(COLUMNS)
|
|
|
|
.from(TABLE)
|
2020-09-18 09:05:09 +02:00
|
|
|
.orderBy('last_seen', 'desc');
|
|
|
|
|
|
|
|
const toggles = rows.map(mapRow);
|
|
|
|
|
|
|
|
stopTimer();
|
|
|
|
|
|
|
|
return toggles;
|
2016-11-04 09:03:13 +01:00
|
|
|
}
|
2016-11-28 17:11:11 +01:00
|
|
|
|
2020-09-18 09:05:09 +02:00
|
|
|
async getByAppName(appName) {
|
|
|
|
const rows = await this.db
|
2016-12-09 17:30:12 +01:00
|
|
|
.select()
|
2016-11-28 17:11:11 +01:00
|
|
|
.from(TABLE)
|
|
|
|
.where('app_name', appName)
|
2020-09-18 09:05:09 +02:00
|
|
|
.orderBy('last_seen', 'desc');
|
|
|
|
|
|
|
|
return rows.map(mapRow);
|
2016-11-28 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2020-09-18 09:05:09 +02:00
|
|
|
async getApplications() {
|
|
|
|
const rows = await this.db
|
2016-11-28 17:11:11 +01:00
|
|
|
.distinct('app_name')
|
|
|
|
.select(['app_name'])
|
|
|
|
.from(TABLE)
|
2020-09-18 09:05:09 +02:00
|
|
|
.orderBy('app_name', 'desc');
|
|
|
|
|
|
|
|
return rows.map(mapRow);
|
2016-11-28 17:11:11 +01:00
|
|
|
}
|
2020-09-25 09:39:12 +02:00
|
|
|
|
|
|
|
async deleteForApplication(appName) {
|
|
|
|
return this.db(TABLE)
|
|
|
|
.where('app_name', appName)
|
|
|
|
.del();
|
|
|
|
}
|
2020-12-16 14:49:11 +01:00
|
|
|
|
|
|
|
destroy() {
|
|
|
|
clearInterval(this.timer);
|
|
|
|
}
|
2017-06-28 10:17:14 +02:00
|
|
|
}
|
2016-11-05 14:08:47 +01:00
|
|
|
|
|
|
|
module.exports = ClientInstanceStore;
|