113 lines
3.5 KiB
JavaScript
113 lines
3.5 KiB
JavaScript
const {EventEmitter} = require('events');
|
|
const {Rotate} = require('./customEvents');
|
|
const {processPeriod} = require('../util/configProcessors');
|
|
const {setTimeout, clearTimeout} = require('long-timeout');
|
|
|
|
const getNextRotation = (period, lastRotation) => {
|
|
var date = new Date();
|
|
|
|
let nextRotation;
|
|
switch (period.unit) {
|
|
case 'ms':
|
|
// Hidden millisecond period for debugging.
|
|
if (lastRotation) {
|
|
nextRotation = lastRotation + period.num;
|
|
} else {
|
|
nextRotation = Date.now() + period.num;
|
|
}
|
|
break;
|
|
case 'h':
|
|
if (lastRotation) {
|
|
nextRotation = lastRotation + period.num * 60 * 60 * 1000;
|
|
} else {
|
|
// First time: top of the next hour.
|
|
nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
|
|
date.getUTCDate(), date.getUTCHours() + 1);
|
|
}
|
|
break;
|
|
case 'd':
|
|
if (lastRotation) {
|
|
nextRotation = lastRotation + period.num * 24 * 60 * 60 * 1000;
|
|
} else {
|
|
// First time: start of tomorrow (i.e. at the coming midnight) UTC.
|
|
nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
|
|
date.getUTCDate() + 1);
|
|
}
|
|
break;
|
|
case 'w':
|
|
// Currently, always on Sunday morning at 00:00:00 (UTC).
|
|
if (lastRotation) {
|
|
nextRotation = lastRotation + period.num * 7 * 24 * 60 * 60 * 1000;
|
|
} else {
|
|
// First time: this coming Sunday.
|
|
nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
|
|
date.getUTCDate() + (7 - date.getUTCDay()));
|
|
}
|
|
break;
|
|
case 'm':
|
|
if (lastRotation) {
|
|
nextRotation = Date.UTC(date.getUTCFullYear(),
|
|
date.getUTCMonth() + period.num, 1);
|
|
} else {
|
|
// First time: the start of the next month.
|
|
nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1);
|
|
}
|
|
break;
|
|
case 'y':
|
|
if (lastRotation) {
|
|
nextRotation = Date.UTC(date.getUTCFullYear() + period.num, 0, 1);
|
|
} else {
|
|
// First time: the start of the next year.
|
|
nextRotation = Date.UTC(date.getUTCFullYear() + 1, 0, 1);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error(`Invalid period scope: "${period.unit}"`);
|
|
}
|
|
|
|
return nextRotation;
|
|
};
|
|
|
|
class PeriodTrigger extends EventEmitter {
|
|
constructor(period, rotateExisting) {
|
|
super();
|
|
this._period = processPeriod(period);
|
|
this._rotateExisting = rotateExisting;
|
|
this._task = null;
|
|
this._rotateAt = null;
|
|
}
|
|
|
|
newFile(fileInfo) {
|
|
if (this._rotateExisting) {
|
|
this._rotateAt = fileInfo.birthtimeMs;
|
|
// Only rotate based on the first file once
|
|
this._rotateExisting = false;
|
|
}
|
|
this.setNextTask();
|
|
}
|
|
|
|
shutdown() {
|
|
if (this._task) {
|
|
clearTimeout(this._task);
|
|
}
|
|
}
|
|
|
|
setNextTask() {
|
|
if (this._task) {
|
|
clearTimeout(this._task);
|
|
}
|
|
this._rotateAt = getNextRotation(this._period, this._rotateAt);
|
|
this._task = setTimeout(() => {
|
|
this._emitRotate();
|
|
this.setNextTask();
|
|
}, Math.max(this._rotateAt - Date.now(), 0));
|
|
// Prevent timeout from keeping Node.js alive
|
|
this._task.unref();
|
|
}
|
|
|
|
_emitRotate() {
|
|
this.emit(Rotate);
|
|
}
|
|
}
|
|
|
|
module.exports = PeriodTrigger; |