mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-08 01:15:49 +02:00
fix: be explicit when specifying time & replace moment with date-fns (#1072)
This commit is contained in:
parent
55bec22754
commit
b47e228181
@ -99,7 +99,6 @@
|
||||
"log4js": "^6.0.0",
|
||||
"memoizee": "^0.4.15",
|
||||
"mime": "^2.4.2",
|
||||
"moment": "^2.24.0",
|
||||
"multer": "^1.4.1",
|
||||
"mustache": "^4.1.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
import { getDefaultLogProvider, LogLevel, validateLogProvider } from './logger';
|
||||
import { defaultCustomAuthDenyAll } from './default-custom-auth-deny-all';
|
||||
import { formatBaseUri } from './util/format-base-uri';
|
||||
import { minutesToMilliseconds, secondsToMilliseconds } from 'date-fns';
|
||||
|
||||
const safeToUpper = (s: string) => (s ? s.toUpperCase() : s);
|
||||
|
||||
@ -94,13 +95,13 @@ const defaultDbOptions: IDBOption = {
|
||||
: { rejectUnauthorized: false },
|
||||
driver: 'postgres',
|
||||
version: process.env.DATABASE_VERSION,
|
||||
acquireConnectionTimeout: 30000,
|
||||
acquireConnectionTimeout: secondsToMilliseconds(30),
|
||||
pool: {
|
||||
min: safeNumber(process.env.DATABASE_POOL_MIN, 0),
|
||||
max: safeNumber(process.env.DATABASE_POOL_MAX, 4),
|
||||
idleTimeoutMillis: safeNumber(
|
||||
process.env.DATABASE_POOL_IDLE_TIMEOUT_MS,
|
||||
30000,
|
||||
secondsToMilliseconds(30),
|
||||
),
|
||||
propagateCreateError: false,
|
||||
},
|
||||
@ -120,8 +121,8 @@ const defaultServerOption: IServerOption = {
|
||||
baseUriPath: formatBaseUri(process.env.BASE_URI_PATH),
|
||||
unleashUrl: process.env.UNLEASH_URL || 'http://localhost:4242',
|
||||
serverMetrics: true,
|
||||
keepAliveTimeout: 60 * 1000,
|
||||
headersTimeout: 61 * 1000,
|
||||
keepAliveTimeout: minutesToMilliseconds(1),
|
||||
headersTimeout: secondsToMilliseconds(61),
|
||||
enableRequestLogger: false,
|
||||
gracefulShutdownEnable: safeBoolean(
|
||||
process.env.GRACEFUL_SHUTDOWN_ENABLE,
|
||||
@ -129,7 +130,7 @@ const defaultServerOption: IServerOption = {
|
||||
),
|
||||
gracefulShutdownTimeout: safeNumber(
|
||||
process.env.GRACEFUL_SHUTDOWN_TIMEOUT,
|
||||
1000,
|
||||
secondsToMilliseconds(1),
|
||||
),
|
||||
secret: process.env.UNLEASH_SECRET || 'super-secret',
|
||||
};
|
||||
|
@ -1,12 +1,13 @@
|
||||
import EventEmitter from 'events';
|
||||
import { Knex } from 'knex';
|
||||
import { Logger, LogProvider } from '../logger';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import {
|
||||
IClientInstance,
|
||||
IClientInstanceStore,
|
||||
INewClientInstance,
|
||||
} from '../types/stores/client-instance-store';
|
||||
import { hoursToMilliseconds } from 'date-fns';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
|
||||
const metricsHelper = require('../util/metrics-helper');
|
||||
const { DB_TIME } = require('../metric-events');
|
||||
@ -22,8 +23,6 @@ const COLUMNS = [
|
||||
];
|
||||
const TABLE = 'client_instances';
|
||||
|
||||
const ONE_DAY = 24 * 61 * 60 * 1000;
|
||||
|
||||
const mapRow = (row) => ({
|
||||
appName: row.app_name,
|
||||
instanceId: row.instance_id,
|
||||
@ -65,7 +64,7 @@ export default class ClientInstanceStore implements IClientInstanceStore {
|
||||
});
|
||||
const clearer = () => this._removeInstancesOlderThanTwoDays();
|
||||
setTimeout(clearer, 10).unref();
|
||||
this.timer = setInterval(clearer, ONE_DAY).unref();
|
||||
this.timer = setInterval(clearer, hoursToMilliseconds(24)).unref();
|
||||
}
|
||||
|
||||
async _removeInstancesOlderThanTwoDays(): Promise<void> {
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Logger, LogProvider } from '../logger';
|
||||
import { IClientMetric } from '../types/stores/client-metrics-db';
|
||||
import { minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
const METRICS_COLUMNS = ['id', 'created_at', 'metrics'];
|
||||
const TABLE = 'client_metrics';
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
|
||||
const mapRow = (row) => ({
|
||||
id: row.id,
|
||||
createdAt: row.created_at,
|
||||
@ -24,7 +23,7 @@ export class ClientMetricsDb {
|
||||
// Clear old metrics regularly
|
||||
const clearer = () => this.removeMetricsOlderThanOneHour();
|
||||
setTimeout(clearer, 10).unref();
|
||||
this.timer = setInterval(clearer, ONE_MINUTE).unref();
|
||||
this.timer = setInterval(clearer, minutesToMilliseconds(1)).unref();
|
||||
}
|
||||
|
||||
async removeMetricsOlderThanOneHour(): Promise<void> {
|
||||
|
@ -5,8 +5,7 @@ import { DB_TIME } from '../metric-events';
|
||||
import { ClientMetricsDb } from './client-metrics-db';
|
||||
import { IClientMetric } from '../types/stores/client-metrics-db';
|
||||
import { IClientMetricsStore } from '../types/stores/client-metrics-store';
|
||||
|
||||
const TEN_SECONDS = 10 * 1000;
|
||||
import { secondsToMilliseconds } from 'date-fns';
|
||||
|
||||
export class ClientMetricsStore
|
||||
extends EventEmitter
|
||||
@ -24,7 +23,7 @@ export class ClientMetricsStore
|
||||
private metricsDb: ClientMetricsDb,
|
||||
eventBus: EventEmitter,
|
||||
getLogger: LogProvider,
|
||||
pollInterval = TEN_SECONDS,
|
||||
pollInterval = secondsToMilliseconds(10),
|
||||
) {
|
||||
super();
|
||||
this.logger = getLogger('client-metrics-store.ts.js');
|
||||
|
@ -3,6 +3,7 @@ import { Knex } from 'knex';
|
||||
import { Logger, LogProvider } from '../logger';
|
||||
import NotFoundError from '../error/notfound-error';
|
||||
import { ISession, ISessionStore } from '../types/stores/session-store';
|
||||
import { addDays } from 'date-fns';
|
||||
|
||||
const TABLE = 'unleash_session';
|
||||
|
||||
@ -72,7 +73,7 @@ export default class SessionStore implements ISessionStore {
|
||||
.insert({
|
||||
sid: data.sid,
|
||||
sess: JSON.stringify(data.sess),
|
||||
expired: data.expired || new Date(Date.now() + 86400000),
|
||||
expired: data.expired || addDays(Date.now(), 1),
|
||||
})
|
||||
.returning<ISessionRow>(['sid', 'sess', 'created_at', 'expired']);
|
||||
if (row) {
|
||||
|
@ -3,19 +3,17 @@ import EventEmitter from 'events';
|
||||
import { Knex } from 'knex';
|
||||
import * as events from './metric-events';
|
||||
import {
|
||||
FEATURE_CREATED,
|
||||
FEATURE_UPDATED,
|
||||
FEATURE_ARCHIVED,
|
||||
FEATURE_REVIVED,
|
||||
DB_POOL_UPDATE,
|
||||
FEATURE_ARCHIVED,
|
||||
FEATURE_CREATED,
|
||||
FEATURE_REVIVED,
|
||||
FEATURE_UPDATED,
|
||||
} from './types/events';
|
||||
import { IUnleashConfig } from './types/option';
|
||||
import { IUnleashStores } from './types/stores';
|
||||
import { hoursToMilliseconds, minutesToMilliseconds } from 'date-fns';
|
||||
import Timer = NodeJS.Timer;
|
||||
|
||||
const TWO_HOURS = 2 * 60 * 60 * 1000;
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
|
||||
export default class MetricsMonitor {
|
||||
timer?: Timer;
|
||||
|
||||
@ -111,7 +109,7 @@ export default class MetricsMonitor {
|
||||
collectStaticCounters();
|
||||
this.timer = setInterval(
|
||||
() => collectStaticCounters(),
|
||||
TWO_HOURS,
|
||||
hoursToMilliseconds(2),
|
||||
).unref();
|
||||
|
||||
eventBus.on(
|
||||
@ -199,7 +197,7 @@ export default class MetricsMonitor {
|
||||
this.registerPoolMetrics(db.client.pool, eventBus);
|
||||
this.poolMetricsTimer = setInterval(
|
||||
() => this.registerPoolMetrics(db.client.pool, eventBus),
|
||||
ONE_MINUTE,
|
||||
minutesToMilliseconds(1),
|
||||
);
|
||||
this.poolMetricsTimer.unref();
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
import helmet from 'helmet';
|
||||
import { RequestHandler } from 'express';
|
||||
import { IUnleashConfig } from '../types/option';
|
||||
import { hoursToSeconds } from 'date-fns';
|
||||
|
||||
const secureHeaders: (config: IUnleashConfig) => RequestHandler = (config) => {
|
||||
if (config.secureHeaders) {
|
||||
return helmet({
|
||||
hsts: {
|
||||
maxAge: 63072000,
|
||||
maxAge: hoursToSeconds(24 * 365 * 2), // 2 non-leap years
|
||||
includeSubDomains: true,
|
||||
preload: true,
|
||||
},
|
||||
|
@ -3,16 +3,16 @@ import session from 'express-session';
|
||||
import knexSessionStore from 'connect-session-knex';
|
||||
import { RequestHandler } from 'express';
|
||||
import { IUnleashConfig } from '../types/option';
|
||||
import { hoursToMilliseconds } from 'date-fns';
|
||||
|
||||
const TWO_DAYS = 48 * 60 * 60 * 1000;
|
||||
const HOUR = 60 * 60 * 1000;
|
||||
function sessionDb(
|
||||
config: Pick<IUnleashConfig, 'session' | 'server' | 'secureHeaders'>,
|
||||
knex: Knex,
|
||||
): RequestHandler {
|
||||
let store;
|
||||
const { db } = config.session;
|
||||
const age = config.session.ttlHours * HOUR || TWO_DAYS;
|
||||
const age =
|
||||
hoursToMilliseconds(config.session.ttlHours) || hoursToMilliseconds(48);
|
||||
const KnexSessionStore = knexSessionStore(session);
|
||||
if (db) {
|
||||
store = new KnexSessionStore({
|
||||
@ -41,4 +41,5 @@ function sessionDb(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default sessionDb;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as mime from 'mime';
|
||||
import YAML from 'js-yaml';
|
||||
import moment from 'moment';
|
||||
import multer from 'multer';
|
||||
import { format as formatDate } from 'date-fns';
|
||||
import { Request, Response } from 'express';
|
||||
import Controller from '../controller';
|
||||
import { ADMIN } from '../../types/permissions';
|
||||
@ -88,7 +88,7 @@ class StateController extends Controller {
|
||||
includeTags,
|
||||
includeEnvironments,
|
||||
});
|
||||
const timestamp = moment().format('YYYY-MM-DD_HH-mm-ss');
|
||||
const timestamp = formatDate(Date.now(), 'yyyy-MM-dd_HH-mm-ss');
|
||||
if (format === 'yaml') {
|
||||
if (downloadFile) {
|
||||
res.attachment(`export-${timestamp}.yml`);
|
||||
|
@ -6,6 +6,7 @@ import getApp from '../../app';
|
||||
import { createServices } from '../../services';
|
||||
import FeatureController from './feature';
|
||||
import { createTestConfig } from '../../../test/config/test-config';
|
||||
import { secondsToMilliseconds } from 'date-fns';
|
||||
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
@ -74,7 +75,7 @@ test('if caching is enabled should memoize', async () => {
|
||||
experimental: {
|
||||
clientFeatureMemoize: {
|
||||
enabled: true,
|
||||
maxAge: 10000,
|
||||
maxAge: secondsToMilliseconds(10),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -100,7 +101,7 @@ test('if caching is not enabled all calls goes to service', async () => {
|
||||
experimental: {
|
||||
clientFeatureMemoize: {
|
||||
enabled: false,
|
||||
maxAge: 10000,
|
||||
maxAge: secondsToMilliseconds(10),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -12,11 +12,10 @@ import { IAddon, IAddonDto, IAddonStore } from '../types/stores/addon-store';
|
||||
import { IUnleashStores } from '../types/stores';
|
||||
import { IUnleashConfig } from '../types/option';
|
||||
import { IAddonDefinition } from '../types/model';
|
||||
import { minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
const SUPPORTED_EVENTS = Object.keys(events).map((k) => events[k]);
|
||||
|
||||
const ADDONS_CACHE_TIME = 60 * 1000; // 60s
|
||||
|
||||
const MASKED_VALUE = '*****';
|
||||
|
||||
interface ISensitiveParams {
|
||||
@ -75,7 +74,7 @@ export default class AddonService {
|
||||
async () => addonStore.getAll({ enabled: true }),
|
||||
{
|
||||
promise: true,
|
||||
maxAge: ADDONS_CACHE_TIME,
|
||||
maxAge: minutesToMilliseconds(1),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ import {
|
||||
import { IApiTokenStore } from '../types/stores/api-token-store';
|
||||
import { FOREIGN_KEY_VIOLATION } from '../error/db-error';
|
||||
import BadDataError from '../error/bad-data-error';
|
||||
|
||||
const ONE_MINUTE = 60_000;
|
||||
import { minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
export class ApiTokenService {
|
||||
private store: IApiTokenStore;
|
||||
@ -34,7 +33,7 @@ export class ApiTokenService {
|
||||
this.fetchActiveTokens();
|
||||
this.timer = setInterval(
|
||||
() => this.fetchActiveTokens(),
|
||||
ONE_MINUTE,
|
||||
minutesToMilliseconds(1),
|
||||
).unref();
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,7 @@ import {
|
||||
IClientMetricsStoreV2,
|
||||
} from '../../types/stores/client-metrics-store-v2';
|
||||
import { clientMetricsSchema } from './client-metrics-schema';
|
||||
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
const ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
import { hoursToMilliseconds, minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
export default class ClientMetricsServiceV2 {
|
||||
private timer: NodeJS.Timeout;
|
||||
@ -24,7 +22,7 @@ export default class ClientMetricsServiceV2 {
|
||||
constructor(
|
||||
{ clientMetricsStoreV2 }: Pick<IUnleashStores, 'clientMetricsStoreV2'>,
|
||||
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
||||
bulkInterval = FIVE_MINUTES,
|
||||
bulkInterval = minutesToMilliseconds(5),
|
||||
) {
|
||||
this.clientMetricsStoreV2 = clientMetricsStoreV2;
|
||||
|
||||
@ -33,7 +31,7 @@ export default class ClientMetricsServiceV2 {
|
||||
this.bulkInterval = bulkInterval;
|
||||
this.timer = setInterval(() => {
|
||||
this.clientMetricsStoreV2.clearMetrics(48);
|
||||
}, ONE_DAY);
|
||||
}, hoursToMilliseconds(24));
|
||||
this.timer.unref();
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,51 @@
|
||||
import EventEmitter from 'events';
|
||||
import moment from 'moment';
|
||||
import ClientMetricsService from './index';
|
||||
import getLogger from '../../../test/fixtures/no-logger';
|
||||
import { IClientApp } from '../../types/model';
|
||||
import {
|
||||
addHours,
|
||||
addMinutes,
|
||||
hoursToMilliseconds,
|
||||
minutesToMilliseconds,
|
||||
secondsToMilliseconds,
|
||||
subHours,
|
||||
subMinutes,
|
||||
subSeconds,
|
||||
} from 'date-fns';
|
||||
|
||||
/**
|
||||
* A utility to wait for any pending promises in the test subject code.
|
||||
* For instance, if the test needs to wait for a timeout/interval handler,
|
||||
* and that handler does something async, advancing the timers is not enough:
|
||||
* We have to explicitly wait for the second promise.
|
||||
* For more info, see https://stackoverflow.com/a/51045733/2868829
|
||||
*
|
||||
* Usage in test code after advancing timers, but before making assertions:
|
||||
*
|
||||
* test('hello', async () => {
|
||||
* jest.useFakeTimers('modern');
|
||||
*
|
||||
* // Schedule a timeout with a callback that does something async
|
||||
* // before calling our spy
|
||||
* const spy = jest.fn();
|
||||
* setTimeout(async () => {
|
||||
* await Promise.resolve();
|
||||
* spy();
|
||||
* }, 1000);
|
||||
*
|
||||
* expect(spy).not.toHaveBeenCalled();
|
||||
*
|
||||
* jest.advanceTimersByTime(1500);
|
||||
* await flushPromises(); // this is required to make it work!
|
||||
*
|
||||
* expect(spy).toHaveBeenCalledTimes(1);
|
||||
*
|
||||
* jest.useRealTimers();
|
||||
* });
|
||||
*/
|
||||
function flushPromises() {
|
||||
return Promise.resolve(setImmediate);
|
||||
}
|
||||
|
||||
const appName = 'appName';
|
||||
const instanceId = 'instanceId';
|
||||
@ -40,8 +83,8 @@ test('data should expire', () => {
|
||||
appName,
|
||||
instanceId,
|
||||
bucket: {
|
||||
start: Date.now() - 2000,
|
||||
stop: Date.now() - 1000,
|
||||
start: subSeconds(Date.now(), 2),
|
||||
stop: subSeconds(Date.now(), 1),
|
||||
toggles: {
|
||||
toggleX: {
|
||||
yes: 123,
|
||||
@ -61,11 +104,11 @@ test('data should expire', () => {
|
||||
lastMinExpires++;
|
||||
});
|
||||
|
||||
jest.advanceTimersByTime(60 * 1000);
|
||||
jest.advanceTimersByTime(minutesToMilliseconds(1));
|
||||
expect(lastMinExpires).toBe(1);
|
||||
expect(lastHourExpires).toBe(0);
|
||||
|
||||
jest.advanceTimersByTime(60 * 60 * 1000);
|
||||
jest.advanceTimersByTime(hoursToMilliseconds(1));
|
||||
expect(lastMinExpires).toBe(1);
|
||||
expect(lastHourExpires).toBe(1);
|
||||
|
||||
@ -201,36 +244,36 @@ test('should have correct values for lastMinute', () => {
|
||||
const now = new Date();
|
||||
const input = [
|
||||
{
|
||||
start: moment(now).subtract(1, 'hour'),
|
||||
stop: moment(now).subtract(59, 'minutes'),
|
||||
start: subHours(now, 1),
|
||||
stop: subMinutes(now, 59),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).subtract(30, 'minutes'),
|
||||
stop: moment(now).subtract(29, 'minutes'),
|
||||
start: subMinutes(now, 30),
|
||||
stop: subMinutes(now, 29),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).subtract(2, 'minutes'),
|
||||
stop: moment(now).subtract(1, 'minutes'),
|
||||
start: subMinutes(now, 2),
|
||||
stop: subMinutes(now, 1),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).subtract(2, 'minutes'),
|
||||
stop: moment(now).subtract(59, 'seconds'),
|
||||
start: subMinutes(now, 2),
|
||||
stop: subSeconds(now, 59),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now),
|
||||
stop: moment(now).subtract(30, 'seconds'),
|
||||
start: now,
|
||||
stop: subSeconds(now, 30),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
@ -252,11 +295,11 @@ test('should have correct values for lastMinute', () => {
|
||||
let c = metrics.getTogglesMetrics();
|
||||
expect(c.lastMinute.toggle).toEqual({ yes: 20, no: 20 });
|
||||
|
||||
jest.advanceTimersByTime(10 * 1000);
|
||||
jest.advanceTimersByTime(10_000);
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastMinute.toggle).toEqual({ yes: 10, no: 10 });
|
||||
|
||||
jest.advanceTimersByTime(20 * 1000);
|
||||
jest.advanceTimersByTime(20_000);
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastMinute.toggle).toEqual({ yes: 0, no: 0 });
|
||||
|
||||
@ -270,32 +313,32 @@ test('should have correct values for lastHour', () => {
|
||||
const clientMetricsStore = new EventEmitter();
|
||||
const metrics = createMetricsService(clientMetricsStore);
|
||||
|
||||
const now = new Date();
|
||||
const now = Date.now();
|
||||
const input = [
|
||||
{
|
||||
start: moment(now).subtract(1, 'hour'),
|
||||
stop: moment(now).subtract(59, 'minutes'),
|
||||
start: subHours(now, 1),
|
||||
stop: subMinutes(now, 59),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).subtract(30, 'minutes'),
|
||||
stop: moment(now).subtract(29, 'minutes'),
|
||||
start: subMinutes(now, 30),
|
||||
stop: subMinutes(now, 29),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).subtract(15, 'minutes'),
|
||||
stop: moment(now).subtract(14, 'minutes'),
|
||||
start: subMinutes(now, 15),
|
||||
stop: subMinutes(now, 14),
|
||||
toggles: {
|
||||
toggle: { yes: 10, no: 10 },
|
||||
},
|
||||
},
|
||||
{
|
||||
start: moment(now).add(59, 'minutes'),
|
||||
stop: moment(now).add(1, 'hour'),
|
||||
start: addMinutes(now, 59),
|
||||
stop: addHours(now, 1),
|
||||
toggles: {
|
||||
toggle: { yes: 11, no: 11 },
|
||||
},
|
||||
@ -318,27 +361,27 @@ test('should have correct values for lastHour', () => {
|
||||
let c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 41, no: 41 });
|
||||
|
||||
jest.advanceTimersByTime(10 * 1000);
|
||||
jest.advanceTimersByTime(10_000);
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 41, no: 41 });
|
||||
|
||||
// at 30
|
||||
jest.advanceTimersByTime(30 * 60 * 1000);
|
||||
jest.advanceTimersByTime(minutesToMilliseconds(30));
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 31, no: 31 });
|
||||
|
||||
// at 45
|
||||
jest.advanceTimersByTime(15 * 60 * 1000);
|
||||
jest.advanceTimersByTime(minutesToMilliseconds(15));
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 21, no: 21 });
|
||||
|
||||
// at 1:15
|
||||
jest.advanceTimersByTime(30 * 60 * 1000);
|
||||
jest.advanceTimersByTime(minutesToMilliseconds(30));
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 11, no: 11 });
|
||||
|
||||
// at 2:00
|
||||
jest.advanceTimersByTime(45 * 60 * 1000);
|
||||
jest.advanceTimersByTime(minutesToMilliseconds(45));
|
||||
c = metrics.getTogglesMetrics();
|
||||
expect(c.lastHour.toggle).toEqual({ yes: 0, no: 0 });
|
||||
|
||||
@ -421,7 +464,8 @@ test('Multiple registrations of same appname and instanceid within same time per
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await jest.advanceTimersByTime(7 * 1000);
|
||||
jest.advanceTimersByTime(7000);
|
||||
await flushPromises();
|
||||
|
||||
expect(appStoreSpy).toHaveBeenCalledTimes(1);
|
||||
expect(bulkSpy).toHaveBeenCalledTimes(1);
|
||||
@ -448,6 +492,7 @@ test('Multiple unique clients causes multiple registrations', async () => {
|
||||
const clientInstanceStore: any = {
|
||||
bulkUpsert: bulkSpy,
|
||||
};
|
||||
|
||||
const clientMetrics = new ClientMetricsService(
|
||||
{
|
||||
clientMetricsStore,
|
||||
@ -479,10 +524,9 @@ test('Multiple unique clients causes multiple registrations', async () => {
|
||||
await clientMetrics.registerClient(client2, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client2, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client2, '127.0.0.1');
|
||||
await jest.advanceTimersByTime(7 * 1000);
|
||||
|
||||
expect(appStoreSpy).toHaveBeenCalledTimes(1);
|
||||
expect(bulkSpy).toHaveBeenCalledTimes(1);
|
||||
jest.advanceTimersByTime(7000);
|
||||
await flushPromises();
|
||||
|
||||
const registrations = appStoreSpy.mock.calls[0][0];
|
||||
|
||||
@ -501,7 +545,7 @@ test('Same client registered outside of dedup interval will be registered twice'
|
||||
bulkUpsert: bulkSpy,
|
||||
};
|
||||
|
||||
const bulkInterval = 2000;
|
||||
const bulkInterval = secondsToMilliseconds(2);
|
||||
|
||||
const clientMetrics = new ClientMetricsService(
|
||||
{
|
||||
@ -525,11 +569,16 @@ test('Same client registered outside of dedup interval will be registered twice'
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await jest.advanceTimersByTime(3 * 1000);
|
||||
|
||||
jest.advanceTimersByTime(3000);
|
||||
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await clientMetrics.registerClient(client1, '127.0.0.1');
|
||||
await jest.advanceTimersByTime(3 * 1000);
|
||||
|
||||
jest.advanceTimersByTime(3000);
|
||||
await flushPromises();
|
||||
|
||||
expect(appStoreSpy).toHaveBeenCalledTimes(2);
|
||||
expect(bulkSpy).toHaveBeenCalledTimes(2);
|
||||
|
||||
@ -552,8 +601,7 @@ test('No registrations during a time period will not call stores', async () => {
|
||||
const clientInstanceStore: any = {
|
||||
bulkUpsert: bulkSpy,
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const clientMetrics = new ClientMetricsService(
|
||||
new ClientMetricsService(
|
||||
{
|
||||
clientMetricsStore,
|
||||
strategyStore: null,
|
||||
@ -564,7 +612,7 @@ test('No registrations during a time period will not call stores', async () => {
|
||||
},
|
||||
{ getLogger },
|
||||
);
|
||||
await jest.advanceTimersByTime(6 * 1000);
|
||||
jest.advanceTimersByTime(6000);
|
||||
expect(appStoreSpy).toHaveBeenCalledTimes(0);
|
||||
expect(bulkSpy).toHaveBeenCalledTimes(0);
|
||||
jest.useRealTimers();
|
||||
|
@ -21,12 +21,9 @@ import {
|
||||
IMetricCounts,
|
||||
IMetricsBucket,
|
||||
} from '../../types/model';
|
||||
|
||||
import TTLList = require('./ttl-list');
|
||||
import { clientRegisterSchema } from './register-schema';
|
||||
|
||||
const FIVE_SECONDS = 5 * 1000;
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
import { minutesToMilliseconds, secondsToMilliseconds } from 'date-fns';
|
||||
import TTLList = require('./ttl-list');
|
||||
|
||||
export default class ClientMetricsService {
|
||||
globalCount = 0;
|
||||
@ -38,13 +35,13 @@ export default class ClientMetricsService {
|
||||
lastMinuteProjection = new Projection();
|
||||
|
||||
lastHourList = new TTLList({
|
||||
interval: 10000,
|
||||
interval: secondsToMilliseconds(10),
|
||||
});
|
||||
|
||||
logger = null;
|
||||
|
||||
lastMinuteList = new TTLList({
|
||||
interval: 10000,
|
||||
interval: secondsToMilliseconds(10),
|
||||
expireType: 'minutes',
|
||||
expireAmount: 1,
|
||||
});
|
||||
@ -87,8 +84,8 @@ export default class ClientMetricsService {
|
||||
| 'eventStore'
|
||||
>,
|
||||
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
||||
bulkInterval = FIVE_SECONDS,
|
||||
announcementInterval = FIVE_MINUTES,
|
||||
bulkInterval = secondsToMilliseconds(5),
|
||||
announcementInterval = minutesToMilliseconds(5),
|
||||
) {
|
||||
this.clientMetricsStore = clientMetricsStore;
|
||||
this.strategyStore = strategyStore;
|
||||
|
@ -1,13 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const moment = require('moment');
|
||||
const List = require('./list');
|
||||
const {
|
||||
add,
|
||||
isFuture,
|
||||
addMilliseconds,
|
||||
secondsToMilliseconds,
|
||||
} = require('date-fns');
|
||||
|
||||
// this list must have entries with sorted ttl range
|
||||
module.exports = class TTLList extends EventEmitter {
|
||||
constructor({
|
||||
interval = 1000,
|
||||
interval = secondsToMilliseconds(1),
|
||||
expireAmount = 1,
|
||||
expireType = 'hours',
|
||||
} = {}) {
|
||||
@ -16,6 +21,14 @@ module.exports = class TTLList extends EventEmitter {
|
||||
this.expireAmount = expireAmount;
|
||||
this.expireType = expireType;
|
||||
|
||||
this.getExpiryFrom = (timestamp) => {
|
||||
if (this.expireType === 'milliseconds') {
|
||||
return addMilliseconds(timestamp, expireAmount);
|
||||
} else {
|
||||
return add(timestamp, { [expireType]: expireAmount });
|
||||
}
|
||||
};
|
||||
|
||||
this.list = new List();
|
||||
|
||||
this.list.on('evicted', ({ value, ttl }) => {
|
||||
@ -36,8 +49,8 @@ module.exports = class TTLList extends EventEmitter {
|
||||
}
|
||||
|
||||
add(value, timestamp = new Date()) {
|
||||
const ttl = moment(timestamp).add(this.expireAmount, this.expireType);
|
||||
if (moment().isBefore(ttl)) {
|
||||
const ttl = this.getExpiryFrom(timestamp);
|
||||
if (isFuture(ttl)) {
|
||||
this.list.add({ ttl, value });
|
||||
} else {
|
||||
this.emit('expire', value, ttl);
|
||||
@ -45,17 +58,13 @@ module.exports = class TTLList extends EventEmitter {
|
||||
}
|
||||
|
||||
timedCheck() {
|
||||
const now = moment();
|
||||
this.list.reverseRemoveUntilTrue(({ value }) =>
|
||||
now.isBefore(value.ttl),
|
||||
);
|
||||
this.list.reverseRemoveUntilTrue(({ value }) => isFuture(value.ttl));
|
||||
this.startTimer();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// https://github.com/nodejs/node/issues/9561
|
||||
// clearTimeout(this.timer);
|
||||
// this.timer = null;
|
||||
clearTimeout(this.timer);
|
||||
this.timer = null;
|
||||
this.list = null;
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const moment = require('moment');
|
||||
const TTLList = require('./ttl-list');
|
||||
const { addMilliseconds } = require('date-fns');
|
||||
|
||||
test('should emit expire', (done) => {
|
||||
jest.useFakeTimers('modern');
|
||||
@ -31,10 +31,10 @@ test('should slice off list', () => {
|
||||
expireType: 'milliseconds',
|
||||
});
|
||||
|
||||
list.add({ n: '1' }, moment().add(1, 'milliseconds'));
|
||||
list.add({ n: '2' }, moment().add(50, 'milliseconds'));
|
||||
list.add({ n: '3' }, moment().add(200, 'milliseconds'));
|
||||
list.add({ n: '4' }, moment().add(300, 'milliseconds'));
|
||||
list.add({ n: '1' }, addMilliseconds(Date.now(), 1));
|
||||
list.add({ n: '2' }, addMilliseconds(Date.now(), 50));
|
||||
list.add({ n: '3' }, addMilliseconds(Date.now(), 200));
|
||||
list.add({ n: '4' }, addMilliseconds(Date.now(), 300));
|
||||
|
||||
const expired = [];
|
||||
|
||||
@ -43,18 +43,45 @@ test('should slice off list', () => {
|
||||
expired.push(entry);
|
||||
});
|
||||
|
||||
expect(expired).toHaveLength(0);
|
||||
expect(list.list.toArray()).toHaveLength(4);
|
||||
|
||||
jest.advanceTimersByTime(21);
|
||||
expect(expired).toHaveLength(1);
|
||||
expect(list.list.toArray()).toHaveLength(3);
|
||||
|
||||
jest.advanceTimersByTime(51);
|
||||
expect(expired).toHaveLength(2);
|
||||
expect(list.list.toArray()).toHaveLength(2);
|
||||
|
||||
jest.advanceTimersByTime(201);
|
||||
expect(expired).toHaveLength(3);
|
||||
expect(list.list.toArray()).toHaveLength(1);
|
||||
|
||||
jest.advanceTimersByTime(301);
|
||||
expect(expired).toHaveLength(4);
|
||||
expect(list.list.toArray()).toHaveLength(0);
|
||||
|
||||
list.destroy();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('should add item created in the past but expiring in the future', () => {
|
||||
jest.useFakeTimers('modern');
|
||||
|
||||
const list = new TTLList({
|
||||
interval: 10,
|
||||
expireAmount: 10,
|
||||
expireType: 'milliseconds',
|
||||
});
|
||||
|
||||
const expireCallback = jest.fn();
|
||||
list.on('expire', expireCallback);
|
||||
|
||||
list.add({ n: '1' }, new Date());
|
||||
|
||||
expect(expireCallback).not.toHaveBeenCalled();
|
||||
expect(list.list.toArray()).toHaveLength(1);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
@ -8,15 +8,12 @@ import {
|
||||
IProjectHealthReport,
|
||||
IProjectOverview,
|
||||
} from '../types/model';
|
||||
import {
|
||||
MILLISECONDS_IN_DAY,
|
||||
MILLISECONDS_IN_ONE_HOUR,
|
||||
} from '../util/constants';
|
||||
import { IFeatureToggleStore } from '../types/stores/feature-toggle-store';
|
||||
import { IFeatureTypeStore } from '../types/stores/feature-type-store';
|
||||
import { IProjectStore } from '../types/stores/project-store';
|
||||
import Timer = NodeJS.Timer;
|
||||
import FeatureToggleServiceV2 from './feature-toggle-service-v2';
|
||||
import { hoursToMilliseconds } from 'date-fns';
|
||||
import Timer = NodeJS.Timer;
|
||||
|
||||
export default class ProjectHealthService {
|
||||
private logger: Logger;
|
||||
@ -52,7 +49,7 @@ export default class ProjectHealthService {
|
||||
this.featureTypes = new Map();
|
||||
this.healthRatingTimer = setInterval(
|
||||
() => this.setHealthRating(),
|
||||
MILLISECONDS_IN_ONE_HOUR,
|
||||
hoursToMilliseconds(1),
|
||||
).unref();
|
||||
this.featureToggleService = featureToggleService;
|
||||
}
|
||||
@ -116,7 +113,7 @@ export default class ProjectHealthService {
|
||||
);
|
||||
return (
|
||||
!feature.stale &&
|
||||
diff >= featureTypeExpectedLifetime * MILLISECONDS_IN_DAY
|
||||
diff >= featureTypeExpectedLifetime * hoursToMilliseconds(24)
|
||||
);
|
||||
}).length;
|
||||
}
|
||||
|
@ -11,8 +11,7 @@ import {
|
||||
IResetToken,
|
||||
IResetTokenStore,
|
||||
} from '../types/stores/reset-token-store';
|
||||
|
||||
const ONE_DAY = 86_400_000;
|
||||
import { hoursToMilliseconds } from 'date-fns';
|
||||
|
||||
interface IInviteLinks {
|
||||
[key: string]: string;
|
||||
@ -106,7 +105,7 @@ export default class ResetTokenService {
|
||||
async createToken(
|
||||
tokenUser: number,
|
||||
creator: string,
|
||||
expiryDelta: number = ONE_DAY,
|
||||
expiryDelta: number = hoursToMilliseconds(24),
|
||||
): Promise<IResetToken> {
|
||||
const token = await this.generateToken();
|
||||
const expiry = new Date(Date.now() + expiryDelta);
|
||||
|
@ -4,8 +4,7 @@ import { IUnleashConfig } from '../types/option';
|
||||
import version from '../util/version';
|
||||
import { Logger } from '../logger';
|
||||
import { ISettingStore } from '../types/stores/settings-store';
|
||||
|
||||
const TWO_DAYS = 48 * 60 * 60 * 1000;
|
||||
import { hoursToMilliseconds } from 'date-fns';
|
||||
|
||||
export interface IVersionInfo {
|
||||
oss: string;
|
||||
@ -66,7 +65,7 @@ export default class VersionService {
|
||||
await this.checkLatestVersion();
|
||||
this.timer = setInterval(
|
||||
async () => this.checkLatestVersion(),
|
||||
TWO_DAYS,
|
||||
hoursToMilliseconds(48),
|
||||
);
|
||||
this.timer.unref();
|
||||
}
|
||||
|
@ -1,3 +1 @@
|
||||
export const MILLISECONDS_IN_DAY = 86400000;
|
||||
export const MILLISECONDS_IN_ONE_HOUR = 3600000;
|
||||
export const DEFAULT_ENV = 'default';
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { log } from 'db-migrate-shared';
|
||||
import { getInstance } from 'db-migrate';
|
||||
import { IUnleashConfig } from './lib/types/option';
|
||||
import { secondsToMilliseconds } from 'date-fns';
|
||||
|
||||
log.setLogLevel('error');
|
||||
|
||||
export async function migrateDb({ db }: IUnleashConfig): Promise<void> {
|
||||
const custom = { ...db, connectionTimeoutMillis: 10000 };
|
||||
const custom = {
|
||||
...db,
|
||||
connectionTimeoutMillis: secondsToMilliseconds(10),
|
||||
};
|
||||
|
||||
const dbm = getInstance(true, {
|
||||
cwd: __dirname,
|
||||
@ -18,7 +22,10 @@ export async function migrateDb({ db }: IUnleashConfig): Promise<void> {
|
||||
|
||||
// This exists to ease testing
|
||||
export async function resetDb({ db }: IUnleashConfig): Promise<void> {
|
||||
const custom = { ...db, connectionTimeoutMillis: 10000 };
|
||||
const custom = {
|
||||
...db,
|
||||
connectionTimeoutMillis: secondsToMilliseconds(10),
|
||||
};
|
||||
|
||||
const dbm = getInstance(true, {
|
||||
cwd: __dirname,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import dbInit from '../../helpers/database-init';
|
||||
import { setupApp } from '../../helpers/test-helper';
|
||||
import getLogger from '../../../fixtures/no-logger';
|
||||
import { parseISO } from 'date-fns';
|
||||
|
||||
let app;
|
||||
let db;
|
||||
@ -28,25 +29,27 @@ beforeEach(async () => {
|
||||
description: 'Some desc',
|
||||
announced: true,
|
||||
});
|
||||
|
||||
const clientStartedDate = parseISO('2018-01-15T14:35:38.494Z');
|
||||
await db.stores.clientInstanceStore.insert({
|
||||
appName: 'demo-app-1',
|
||||
instanceId: 'test-1',
|
||||
strategies: ['default'],
|
||||
started: 1516026938494,
|
||||
started: clientStartedDate,
|
||||
interval: 10,
|
||||
});
|
||||
await db.stores.clientInstanceStore.insert({
|
||||
appName: 'demo-seed-2',
|
||||
instanceId: 'test-2',
|
||||
strategies: ['default'],
|
||||
started: 1516026938494,
|
||||
started: clientStartedDate,
|
||||
interval: 10,
|
||||
});
|
||||
await db.stores.clientInstanceStore.insert({
|
||||
appName: 'deletable-app',
|
||||
instanceId: 'inst-1',
|
||||
strategies: ['default'],
|
||||
started: 1516026938494,
|
||||
started: clientStartedDate,
|
||||
interval: 10,
|
||||
});
|
||||
await app.services.clientMetricsService.addPayload({
|
||||
|
@ -60,7 +60,7 @@ test('should allow client to register multiple times', async () => {
|
||||
.send(clientRegistration)
|
||||
.expect(202);
|
||||
|
||||
jest.advanceTimersByTime(6 * 1000);
|
||||
jest.advanceTimersByTime(6000);
|
||||
expect(clientApplicationsStore.exists(clientRegistration)).toBeTruthy();
|
||||
expect(clientInstanceStore.exists(clientRegistration)).toBeTruthy();
|
||||
jest.useRealTimers();
|
||||
|
@ -78,7 +78,7 @@ test('should only return active addons', async () => {
|
||||
await addonService.createAddon(config2, 'me@mail.com');
|
||||
await addonService.createAddon(config3, 'me@mail.com');
|
||||
|
||||
jest.advanceTimersByTime(61 * 1000);
|
||||
jest.advanceTimersByTime(61_000);
|
||||
|
||||
const activeAddons = await addonService.fetchAddonConfigs();
|
||||
const allAddons = await addonService.getAddons();
|
||||
|
@ -4,6 +4,7 @@ import { ApiTokenService } from '../../../lib/services/api-token-service';
|
||||
import { createTestConfig } from '../../config/test-config';
|
||||
import { ApiTokenType, IApiToken } from '../../../lib/types/models/api-token';
|
||||
import { DEFAULT_ENV } from '../../../lib/util/constants';
|
||||
import { addDays, subDays } from 'date-fns';
|
||||
|
||||
let db;
|
||||
let stores;
|
||||
@ -102,13 +103,14 @@ test('should update expiry of token', async () => {
|
||||
});
|
||||
|
||||
test('should only return valid tokens', async () => {
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
|
||||
const now = Date.now();
|
||||
const yesterday = subDays(now, 1);
|
||||
const tomorrow = addDays(now, 1);
|
||||
|
||||
await apiTokenService.createApiToken({
|
||||
username: 'default-expired',
|
||||
type: ApiTokenType.CLIENT,
|
||||
expiresAt: new Date('2021-01-01'),
|
||||
expiresAt: yesterday,
|
||||
project: '*',
|
||||
environment: DEFAULT_ENV,
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import ClientMetricsService from '../../../lib/services/client-metrics';
|
||||
import { IClientApp } from '../../../lib/types/model';
|
||||
import { secondsToMilliseconds } from 'date-fns';
|
||||
|
||||
const faker = require('faker');
|
||||
const dbInit = require('../helpers/database-init');
|
||||
@ -13,11 +14,15 @@ let clientMetricsService;
|
||||
beforeAll(async () => {
|
||||
db = await dbInit('client_metrics_service_serial', getLogger);
|
||||
stores = db.stores;
|
||||
|
||||
const bulkInterval = secondsToMilliseconds(0.5);
|
||||
const announcementInterval = secondsToMilliseconds(2);
|
||||
|
||||
clientMetricsService = new ClientMetricsService(
|
||||
stores,
|
||||
{ getLogger },
|
||||
500,
|
||||
2000,
|
||||
bulkInterval,
|
||||
announcementInterval,
|
||||
);
|
||||
});
|
||||
|
||||
@ -53,7 +58,7 @@ test('Apps registered should be announced', async () => {
|
||||
const first = await stores.clientApplicationsStore.getUnannounced();
|
||||
expect(first.length).toBe(2);
|
||||
await clientMetricsService.registerClient(clientRegistration, '127.0.0.1');
|
||||
await new Promise((res) => setTimeout(res, 2000));
|
||||
await new Promise((res) => setTimeout(res, secondsToMilliseconds(2)));
|
||||
const second = await stores.clientApplicationsStore.getUnannounced();
|
||||
expect(second.length).toBe(0);
|
||||
const events = await stores.eventStore.getEvents();
|
||||
|
@ -2,6 +2,7 @@ import noLoggerProvider from '../../fixtures/no-logger';
|
||||
import dbInit from '../helpers/database-init';
|
||||
import SessionService from '../../../lib/services/session-service';
|
||||
import NotFoundError from '../../../lib/error/notfound-error';
|
||||
import { addDays, minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
let stores;
|
||||
let db;
|
||||
@ -10,8 +11,8 @@ const newSession = {
|
||||
sid: 'abc123',
|
||||
sess: {
|
||||
cookie: {
|
||||
originalMaxAge: 2880000,
|
||||
expires: new Date(Date.now() + 86_400_000).toDateString(),
|
||||
originalMaxAge: minutesToMilliseconds(48),
|
||||
expires: addDays(Date.now(), 1).toDateString(),
|
||||
secure: false,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
@ -31,8 +32,8 @@ const otherSession = {
|
||||
sid: 'xyz321',
|
||||
sess: {
|
||||
cookie: {
|
||||
originalMaxAge: 2880000,
|
||||
expires: new Date(Date.now() + 86400000).toDateString(),
|
||||
originalMaxAge: minutesToMilliseconds(48),
|
||||
expires: addDays(Date.now(), 1).toDateString(),
|
||||
secure: false,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
|
@ -12,6 +12,7 @@ import { IRole } from '../../../lib/types/stores/access-store';
|
||||
import { RoleName } from '../../../lib/types/model';
|
||||
import SettingService from '../../../lib/services/setting-service';
|
||||
import { simpleAuthKey } from '../../../lib/types/settings/simple-auth-settings';
|
||||
import { addDays, minutesToMilliseconds } from 'date-fns';
|
||||
|
||||
let db;
|
||||
let stores;
|
||||
@ -161,8 +162,8 @@ test("deleting a user should delete the user's sessions", async () => {
|
||||
sid: 'xyz321',
|
||||
sess: {
|
||||
cookie: {
|
||||
originalMaxAge: 2880000,
|
||||
expires: new Date(Date.now() + 86400000).toDateString(),
|
||||
originalMaxAge: minutesToMilliseconds(48),
|
||||
expires: addDays(Date.now(), 1).toDateString(),
|
||||
secure: false,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { subDays } from 'date-fns';
|
||||
import { addHours, set, subDays } from 'date-fns';
|
||||
import dbInit from '../helpers/database-init';
|
||||
import getLogger from '../../fixtures/no-logger';
|
||||
import { IUnleashStores } from '../../../lib/types';
|
||||
@ -66,10 +66,9 @@ test('Should "increment" metrics within same hour', async () => {
|
||||
});
|
||||
|
||||
test('Should get individual metrics outside same hour', async () => {
|
||||
const d1 = new Date();
|
||||
const d2 = new Date();
|
||||
d1.setHours(10, 10, 11);
|
||||
d2.setHours(11, 10, 11);
|
||||
const d1 = set(Date.now(), { hours: 10, minutes: 10, seconds: 11 });
|
||||
const d2 = addHours(d1, 1);
|
||||
|
||||
const metrics: IClientMetricsEnv[] = [
|
||||
{
|
||||
featureName: 'demo',
|
||||
@ -265,7 +264,7 @@ test('Should not fail on undefined list of metrics', async () => {
|
||||
});
|
||||
|
||||
test('Should return delete old metric', async () => {
|
||||
const twoDaysAgo = subDays(new Date(), 2);
|
||||
const twoDaysAgo = subDays(Date.now(), 2);
|
||||
|
||||
const metrics: IClientMetricsEnv[] = [
|
||||
{
|
||||
@ -311,7 +310,7 @@ test('Should return delete old metric', async () => {
|
||||
});
|
||||
|
||||
test('Should get metric', async () => {
|
||||
const twoDaysAgo = subDays(new Date(), 2);
|
||||
const twoDaysAgo = subDays(Date.now(), 2);
|
||||
|
||||
const metrics: IClientMetricsEnv[] = [
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ test('Should be able to store multiple events at once', async () => {
|
||||
const seen = [];
|
||||
eventStore.on(APPLICATION_CREATED, (e) => seen.push(e));
|
||||
await eventStore.batchStore([event1, event2, event3]);
|
||||
await jest.advanceTimersByTime(100);
|
||||
jest.advanceTimersByTime(100);
|
||||
expect(seen.length).toBe(3);
|
||||
seen.forEach((e) => {
|
||||
expect(e.id).toBeTruthy();
|
||||
|
@ -4996,11 +4996,6 @@ module-not-found-error@^1.0.1:
|
||||
resolved "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz"
|
||||
integrity sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=
|
||||
|
||||
moment@^2.24.0:
|
||||
version "2.29.1"
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz"
|
||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||
|
||||
"mongodb-uri@>= 0.9.7":
|
||||
version "0.9.7"
|
||||
resolved "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user