[feature] Add monthOffset param to info.json request

This commit is contained in:
Sergey Konovalov
2021-10-10 19:38:49 +03:00
committed by Sergey Konovalov
parent 69cc86e73c
commit 27d72e3bc9
7 changed files with 85 additions and 9 deletions

View File

@ -188,7 +188,8 @@
"sessionclosecommand": "2m",
"pemStdTTL": "1h",
"pemCheckPeriod": "10m",
"updateVersionStatus": "5m"
"updateVersionStatus": "5m",
"monthUniqueUsers": "1y"
},
"ipfilter": {
"rules": [{"address": "*", "allowed": true}],

View File

@ -228,6 +228,7 @@ exports.REDIS_KEY_PRESENCE_HASH = 'presence:hash:';
exports.REDIS_KEY_PRESENCE_SET = 'presence:set:';
exports.REDIS_KEY_PRESENCE_UNIQUE_USERS = 'presence:unique:users';
exports.REDIS_KEY_PRESENCE_UNIQUE_USERS_HASH = 'presence:unique:users:hash';
exports.REDIS_KEY_PRESENCE_MONTH_UNIQUE_USERS_HASH = 'presence:unique:users:month';
exports.REDIS_KEY_LOCKS = 'locks:';
exports.REDIS_KEY_LOCK_DOCUMENT = 'lockdocument:';
exports.REDIS_KEY_MESSAGE = 'message:';

View File

@ -39,6 +39,8 @@ const oBuildDate = new Date(buildDate);
exports.readLicense = function*() {
const c_LR = constants.LICENSE_RESULT;
var now = new Date();
var startDate = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));//first day of current month
return [{
count: 1,
type: c_LR.Success,
@ -53,6 +55,7 @@ exports.readLicense = function*() {
hasLicense: false,
plugins: false,
buildDate: oBuildDate,
startDate: startDate,
endDate: null
}, null];
};

View File

@ -930,6 +930,7 @@ exports.convertLicenseInfoToFileParams = function(licenseInfo) {
// whiteLabel = false;
// }
let license = {};
license.start_date = licenseInfo.startDate && licenseInfo.startDate.toJSON();
license.end_date = licenseInfo.endDate && licenseInfo.endDate.toJSON();
license.timelimited = 0 !== (constants.LICENSE_MODE.Limited & licenseInfo.mode);
license.trial = 0 !== (constants.LICENSE_MODE.Trial & licenseInfo.mode);
@ -966,3 +967,43 @@ exports.checkBaseUrl = function(baseUrl) {
exports.resolvePath = function(object, path, defaultValue) {
return path.split('.').reduce((o, p) => o ? o[p] : defaultValue, object);
}
Date.isLeapYear = function (year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
};
Date.getDaysInMonth = function (year, month) {
return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};
Date.prototype.isLeapYear = function () {
return Date.isLeapYear(this.getUTCFullYear());
};
Date.prototype.getDaysInMonth = function () {
return Date.getDaysInMonth(this.getUTCFullYear(), this.getUTCMonth());
};
Date.prototype.addMonths = function (value) {
var n = this.getUTCDate();
this.setUTCDate(1);
this.setUTCMonth(this.getUTCMonth() + value);
this.setUTCDate(Math.min(n, this.getDaysInMonth()));
return this;
};
function getMonthDiff(d1, d2) {
var months;
months = (d2.getUTCFullYear() - d1.getUTCFullYear()) * 12;
months -= d1.getUTCMonth();
months += d2.getUTCMonth();
return months;
}
exports.getLicensePeriod = function(startDate, now) {
startDate = new Date(startDate.getTime());//clone
startDate.addMonths(getMonthDiff(startDate, now));
if (startDate > now) {
startDate.addMonths(-1);
}
return startDate.getTime();
};

View File

@ -556,6 +556,8 @@ function* updateEditUsers(userId, anonym) {
const expireAt = (Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1)) / 1000 +
licenseInfo.usersExpire - 1;
yield editorData.addPresenceUniqueUser(userId, expireAt, {anonym: anonym});
let period = utils.getLicensePeriod(licenseInfo.startDate, now);
yield editorData.addPresenceUniqueUsersOfMonth(userId, period, {anonym: anonym, firstOpenDate: now.toISOString()});
}
function* getEditorsCount(docId, opt_hvals) {
var elem, editorsCount = 0;
@ -3313,7 +3315,7 @@ exports.licenseInfo = function(req, res) {
return co(function*() {
let isError = false;
let output = {
connectionsStat: {}, licenseInfo: {}, serverInfo: {
connectionsStat: {}, uniqueUsersOfMonth: {}, licenseInfo: {}, serverInfo: {
buildVersion: commonDefines.buildVersion, buildNumber: commonDefines.buildNumber,
}, quota: {
uniqueUserCount: 0,
@ -3323,10 +3325,12 @@ exports.licenseInfo = function(req, res) {
Object.assign(output.licenseInfo, licenseInfo);
try {
logger.debug('licenseInfo start');
logger.debug(`licenseInfo req.query:%j`, req.query);
let monthOffset = parseInt(req.query['monthoffset']) || 0;
var precisionSum = {};
for (let i = 0; i < PRECISION.length; ++i) {
precisionSum[PRECISION[i].name] = {
edit: {min: Number.MAX_VALUE, sum: 0, count: 0, max: 0, time: null, period: PRECISION[i].val},
edit: {min: Number.MAX_VALUE, sum: 0, count: 0, max: 0},
view: {min: Number.MAX_VALUE, sum: 0, count: 0, max: 0}
};
output.connectionsStat[PRECISION[i].name] = {
@ -3346,7 +3350,6 @@ exports.licenseInfo = function(req, res) {
precision.edit.max = Math.max(precision.edit.max, elem.edit);
precision.edit.sum += elem.edit;
precision.edit.count++;
precision.edit.time = elem.time;
precision.view.min = Math.min(precision.view.min, elem.view);
precision.view.max = Math.max(precision.view.max, elem.view);
precision.view.sum += elem.view;
@ -3359,15 +3362,13 @@ exports.licenseInfo = function(req, res) {
for (let i in precisionSum) {
let precision = precisionSum[i];
let precisionOut = output.connectionsStat[i];
//scale compensates for the lack of points at server start
let scale = (now - precision.edit.time) / precision.edit.period;
if (precision.edit.count > 0) {
precisionOut.edit.avr = Math.round((precision.edit.sum / precision.edit.count) * scale);
precisionOut.edit.avr = Math.round(precision.edit.sum / precision.edit.count);
precisionOut.edit.min = precision.edit.min;
precisionOut.edit.max = precision.edit.max;
}
if (precision.view.count > 0) {
precisionOut.view.avr = Math.round((precision.view.sum / precision.view.count) * scale);
precisionOut.view.avr = Math.round(precision.view.sum / precision.view.count);
precisionOut.view.min = precision.view.min;
precisionOut.view.max = precision.view.max;
}
@ -3380,6 +3381,10 @@ exports.licenseInfo = function(req, res) {
output.quota.anonymousUserCount++;
}
});
let nowClone = new Date(now);//clone
nowClone.addMonths(monthOffset);
let period = utils.getLicensePeriod(licenseInfo.startDate, nowClone);
output.uniqueUsersOfMonth = yield editorData.getPresenceUniqueUsersOfMonth(period);
logger.debug('licenseInfo end');
} catch (err) {
isError = true;

View File

@ -31,13 +31,18 @@
*/
'use strict';
const config = require('config');
const ms = require('ms');
const utils = require('./../../Common/sources/utils');
const commonDefines = require('./../../Common/sources/commondefines');
const cfgExpMonthUniqueUsers = ms(config.get('services.CoAuthoring.expire.monthUniqueUsers'));
function EditorData() {
this.data = {};
this.forceSaveTimer = {};
this.uniqueUser = {};
this.uniqueUsersOfMonth = {};
this.shutdown = {};
this.stat = [];
}
@ -242,6 +247,26 @@ EditorData.prototype.getPresenceUniqueUser = function(nowUTC) {
}
return Promise.resolve(res);
};
EditorData.prototype.addPresenceUniqueUsersOfMonth = function(userId, period, userInfo) {
if(!this.uniqueUsersOfMonth[period]) {
let expireAt = Date.now() + cfgExpMonthUniqueUsers;
this.uniqueUsersOfMonth[period] = {expireAt: expireAt, data: {}};
}
this.uniqueUsersOfMonth[period].data[userId] = userInfo;
return Promise.resolve();
};
EditorData.prototype.getPresenceUniqueUsersOfMonth = function(period) {
let nowUTC = Date.now();
for (let periodId in this.uniqueUsersOfMonth) {
if (this.uniqueUsersOfMonth.hasOwnProperty(periodId)) {
if (this.uniqueUsersOfMonth[periodId].expireAt <= nowUTC) {
delete this.uniqueUsersOfMonth[periodId];
}
}
}
let res = this.uniqueUsersOfMonth[period];
return Promise.resolve(res && res.data || {});
};
EditorData.prototype.setEditorConnections = function(countEdit, countView, now, precision) {
this.stat.push({time: now, edit: countEdit, view: countView});

View File

@ -204,7 +204,7 @@ docsCoServer.install(server, () => {
app.post('/docbuilder', utils.checkClientIp, rawFileParser, (req, res) => {
converterService.builder(req, res);
});
app.get('/info/info.json', utils.checkClientIp, docsCoServer.licenseInfo);
app.get('/info/info.json', utils.checkClientIp, utils.lowercaseQueryString, docsCoServer.licenseInfo);
app.put('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown);
app.delete('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown);