mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
fix: rename metrics-service to client-instance service
This commit is contained in:
parent
4a9939ccb1
commit
9f13b801eb
@ -26,7 +26,7 @@ function getSetup() {
|
|||||||
request: supertest(app),
|
request: supertest(app),
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,7 @@ function getSetup() {
|
|||||||
request: supertest(app),
|
request: supertest(app),
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ function getSetup() {
|
|||||||
perms,
|
perms,
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -4,23 +4,23 @@ import { UPDATE_APPLICATION } from '../../types/permissions';
|
|||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
import { IUnleashServices } from '../../types/services';
|
import { IUnleashServices } from '../../types/services';
|
||||||
import { Logger } from '../../logger';
|
import { Logger } from '../../logger';
|
||||||
import ClientMetricsService from '../../services/client-metrics';
|
import ClientInstanceService from '../../services/client-metrics/client-instance-service';
|
||||||
|
|
||||||
class MetricsController extends Controller {
|
class MetricsController extends Controller {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
private metrics: ClientMetricsService;
|
private clientInstanceService: ClientInstanceService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{
|
{
|
||||||
clientMetricsService,
|
clientInstanceService,
|
||||||
}: Pick<IUnleashServices, 'clientMetricsService'>,
|
}: Pick<IUnleashServices, 'clientInstanceService'>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.logger = config.getLogger('/admin-api/metrics.ts');
|
this.logger = config.getLogger('/admin-api/metrics.ts');
|
||||||
|
|
||||||
this.metrics = clientMetricsService;
|
this.clientInstanceService = clientInstanceService;
|
||||||
|
|
||||||
// deprecated routes
|
// deprecated routes
|
||||||
this.get('/seen-toggles', this.deprecated);
|
this.get('/seen-toggles', this.deprecated);
|
||||||
@ -54,13 +54,13 @@ class MetricsController extends Controller {
|
|||||||
async deleteApplication(req: Request, res: Response): Promise<void> {
|
async deleteApplication(req: Request, res: Response): Promise<void> {
|
||||||
const { appName } = req.params;
|
const { appName } = req.params;
|
||||||
|
|
||||||
await this.metrics.deleteApplication(appName);
|
await this.clientInstanceService.deleteApplication(appName);
|
||||||
res.status(200).end();
|
res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
async createApplication(req: Request, res: Response): Promise<void> {
|
async createApplication(req: Request, res: Response): Promise<void> {
|
||||||
const input = { ...req.body, appName: req.params.appName };
|
const input = { ...req.body, appName: req.params.appName };
|
||||||
await this.metrics.createApplication(input);
|
await this.clientInstanceService.createApplication(input);
|
||||||
res.status(202).end();
|
res.status(202).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +68,18 @@ class MetricsController extends Controller {
|
|||||||
const query = req.query.strategyName
|
const query = req.query.strategyName
|
||||||
? { strategyName: req.query.strategyName as string }
|
? { strategyName: req.query.strategyName as string }
|
||||||
: {};
|
: {};
|
||||||
const applications = await this.metrics.getApplications(query);
|
const applications = await this.clientInstanceService.getApplications(
|
||||||
|
query,
|
||||||
|
);
|
||||||
res.json({ applications });
|
res.json({ applications });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getApplication(req: Request, res: Response): Promise<void> {
|
async getApplication(req: Request, res: Response): Promise<void> {
|
||||||
const { appName } = req.params;
|
const { appName } = req.params;
|
||||||
|
|
||||||
const appDetails = await this.metrics.getApplication(appName);
|
const appDetails = await this.clientInstanceService.getApplication(
|
||||||
|
appName,
|
||||||
|
);
|
||||||
res.json(appDetails);
|
res.json(appDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ function getSetup() {
|
|||||||
|
|
||||||
destroy = () => {
|
destroy = () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ function getSetup() {
|
|||||||
request: supertest(app),
|
request: supertest(app),
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,6 @@ test('should enable prometheus', async () => {
|
|||||||
.expect('Content-Type', /text/)
|
.expect('Content-Type', /text/)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
});
|
});
|
||||||
|
@ -24,7 +24,7 @@ function getSetup() {
|
|||||||
request: supertest(app),
|
request: supertest(app),
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@ function getSetup(opts?: IUnleashOptions) {
|
|||||||
stores,
|
stores,
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import { Response } from 'express';
|
|||||||
import Controller from '../controller';
|
import Controller from '../controller';
|
||||||
import { IUnleashServices } from '../../types';
|
import { IUnleashServices } from '../../types';
|
||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
import ClientMetricsService from '../../services/client-metrics';
|
import ClientInstanceService from '../../services/client-metrics/client-instance-service';
|
||||||
import { Logger } from '../../logger';
|
import { Logger } from '../../logger';
|
||||||
import { IAuthRequest } from '../unleash-types';
|
import { IAuthRequest } from '../unleash-types';
|
||||||
import ApiUser from '../../types/api-user';
|
import ApiUser from '../../types/api-user';
|
||||||
@ -15,17 +15,17 @@ import { NONE } from '../../types/permissions';
|
|||||||
export default class ClientMetricsController extends Controller {
|
export default class ClientMetricsController extends Controller {
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
|
|
||||||
metrics: ClientMetricsService;
|
clientInstanceService: ClientInstanceService;
|
||||||
|
|
||||||
metricsV2: ClientMetricsServiceV2;
|
metricsV2: ClientMetricsServiceV2;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
clientMetricsService,
|
clientInstanceService,
|
||||||
clientMetricsServiceV2,
|
clientMetricsServiceV2,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
IUnleashServices,
|
IUnleashServices,
|
||||||
'clientMetricsService' | 'clientMetricsServiceV2'
|
'clientInstanceService' | 'clientMetricsServiceV2'
|
||||||
>,
|
>,
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
) {
|
) {
|
||||||
@ -33,7 +33,7 @@ export default class ClientMetricsController extends Controller {
|
|||||||
const { getLogger } = config;
|
const { getLogger } = config;
|
||||||
|
|
||||||
this.logger = getLogger('/api/client/metrics');
|
this.logger = getLogger('/api/client/metrics');
|
||||||
this.metrics = clientMetricsService;
|
this.clientInstanceService = clientInstanceService;
|
||||||
this.metricsV2 = clientMetricsServiceV2;
|
this.metricsV2 = clientMetricsServiceV2;
|
||||||
|
|
||||||
this.post('/', this.registerMetrics, NONE);
|
this.post('/', this.registerMetrics, NONE);
|
||||||
@ -53,7 +53,7 @@ export default class ClientMetricsController extends Controller {
|
|||||||
async registerMetrics(req: IAuthRequest, res: Response): Promise<void> {
|
async registerMetrics(req: IAuthRequest, res: Response): Promise<void> {
|
||||||
const { body: data, ip: clientIp, user } = req;
|
const { body: data, ip: clientIp, user } = req;
|
||||||
data.environment = this.resolveEnvironment(user, data);
|
data.environment = this.resolveEnvironment(user, data);
|
||||||
await this.metrics.registerClientMetrics(data, clientIp);
|
await this.clientInstanceService.registerInstance(data, clientIp);
|
||||||
|
|
||||||
await this.metricsV2.registerClientMetrics(data, clientIp);
|
await this.metricsV2.registerClientMetrics(data, clientIp);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ function getSetup() {
|
|||||||
stores,
|
stores,
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@ import Controller from '../controller';
|
|||||||
import { IUnleashServices } from '../../types';
|
import { IUnleashServices } from '../../types';
|
||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
import { Logger } from '../../logger';
|
import { Logger } from '../../logger';
|
||||||
import ClientMetricsService from '../../services/client-metrics';
|
import ClientInstanceService from '../../services/client-metrics/client-instance-service';
|
||||||
import { IAuthRequest, User } from '../../server-impl';
|
import { IAuthRequest, User } from '../../server-impl';
|
||||||
import { IClientApp } from '../../types/model';
|
import { IClientApp } from '../../types/model';
|
||||||
import ApiUser from '../../types/api-user';
|
import ApiUser from '../../types/api-user';
|
||||||
@ -13,17 +13,17 @@ import { NONE } from '../../types/permissions';
|
|||||||
export default class RegisterController extends Controller {
|
export default class RegisterController extends Controller {
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
|
|
||||||
metrics: ClientMetricsService;
|
metrics: ClientInstanceService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
clientMetricsService,
|
clientInstanceService,
|
||||||
}: Pick<IUnleashServices, 'clientMetricsService'>,
|
}: Pick<IUnleashServices, 'clientInstanceService'>,
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.logger = config.getLogger('/api/client/register');
|
this.logger = config.getLogger('/api/client/register');
|
||||||
this.metrics = clientMetricsService;
|
this.metrics = clientInstanceService;
|
||||||
|
|
||||||
// NONE permission is not optimal here in terms of readability.
|
// NONE permission is not optimal here in terms of readability.
|
||||||
this.post('/', this.handleRegister, NONE);
|
this.post('/', this.handleRegister, NONE);
|
||||||
|
@ -18,7 +18,7 @@ function getSetup() {
|
|||||||
stores,
|
stores,
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,7 @@ function getSetup() {
|
|||||||
request: supertest(app),
|
request: supertest(app),
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ import { minutesToMilliseconds, secondsToMilliseconds } from 'date-fns';
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import { IClientMetricsStoreV2 } from '../../types/stores/client-metrics-store-v2';
|
import { IClientMetricsStoreV2 } from '../../types/stores/client-metrics-store-v2';
|
||||||
|
|
||||||
export default class ClientMetricsService {
|
export default class ClientInstanceService {
|
||||||
apps = {};
|
apps = {};
|
||||||
|
|
||||||
logger = null;
|
logger = null;
|
||||||
@ -91,7 +91,7 @@ export default class ClientMetricsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async registerClientMetrics(
|
public async registerInstance(
|
||||||
data: IClientApp,
|
data: IClientApp,
|
||||||
clientIp: string,
|
clientIp: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
@ -1,5 +1,5 @@
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import ClientMetricsService from './index';
|
import ClientInstanceService from './client-instance-service';
|
||||||
import getLogger from '../../../test/fixtures/no-logger';
|
import getLogger from '../../../test/fixtures/no-logger';
|
||||||
import { IClientApp } from '../../types/model';
|
import { IClientApp } from '../../types/model';
|
||||||
import { secondsToMilliseconds } from 'date-fns';
|
import { secondsToMilliseconds } from 'date-fns';
|
||||||
@ -48,7 +48,7 @@ test('Multiple registrations of same appname and instanceid within same time per
|
|||||||
const clientInstanceStore: any = {
|
const clientInstanceStore: any = {
|
||||||
bulkUpsert: bulkSpy,
|
bulkUpsert: bulkSpy,
|
||||||
};
|
};
|
||||||
const clientMetrics = new ClientMetricsService(
|
const clientMetrics = new ClientInstanceService(
|
||||||
{
|
{
|
||||||
clientMetricsStoreV2: null,
|
clientMetricsStoreV2: null,
|
||||||
strategyStore: null,
|
strategyStore: null,
|
||||||
@ -98,7 +98,7 @@ test('Multiple unique clients causes multiple registrations', async () => {
|
|||||||
bulkUpsert: bulkSpy,
|
bulkUpsert: bulkSpy,
|
||||||
};
|
};
|
||||||
|
|
||||||
const clientMetrics = new ClientMetricsService(
|
const clientMetrics = new ClientInstanceService(
|
||||||
{
|
{
|
||||||
clientMetricsStoreV2: null,
|
clientMetricsStoreV2: null,
|
||||||
strategyStore: null,
|
strategyStore: null,
|
||||||
@ -151,7 +151,7 @@ test('Same client registered outside of dedup interval will be registered twice'
|
|||||||
|
|
||||||
const bulkInterval = secondsToMilliseconds(2);
|
const bulkInterval = secondsToMilliseconds(2);
|
||||||
|
|
||||||
const clientMetrics = new ClientMetricsService(
|
const clientMetrics = new ClientInstanceService(
|
||||||
{
|
{
|
||||||
clientMetricsStoreV2: null,
|
clientMetricsStoreV2: null,
|
||||||
strategyStore: null,
|
strategyStore: null,
|
||||||
@ -204,7 +204,7 @@ test('No registrations during a time period will not call stores', async () => {
|
|||||||
const clientInstanceStore: any = {
|
const clientInstanceStore: any = {
|
||||||
bulkUpsert: bulkSpy,
|
bulkUpsert: bulkSpy,
|
||||||
};
|
};
|
||||||
new ClientMetricsService(
|
new ClientInstanceService(
|
||||||
{
|
{
|
||||||
clientMetricsStoreV2: null,
|
clientMetricsStoreV2: null,
|
||||||
strategyStore: null,
|
strategyStore: null,
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
import List from './list';
|
|
||||||
|
|
||||||
function getList() {
|
|
||||||
const list = new List<number>();
|
|
||||||
list.add(1);
|
|
||||||
list.add(2);
|
|
||||||
list.add(3);
|
|
||||||
list.add(4);
|
|
||||||
list.add(5);
|
|
||||||
list.add(6);
|
|
||||||
list.add(7);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
test('should emit "evicted" events for objects leaving list', () => {
|
|
||||||
const list = getList();
|
|
||||||
const evictedList = [];
|
|
||||||
list.on('evicted', (value) => {
|
|
||||||
evictedList.push(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(evictedList.length === 0).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(({ value }) => {
|
|
||||||
if (value === 4) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(evictedList.length === 3).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(() => false);
|
|
||||||
|
|
||||||
expect(evictedList.length === 7).toBe(true);
|
|
||||||
|
|
||||||
list.add(1);
|
|
||||||
list.reverseRemoveUntilTrue(() => false);
|
|
||||||
|
|
||||||
expect(evictedList.length === 8).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('list should be able remove until given value', () => {
|
|
||||||
const list = getList();
|
|
||||||
|
|
||||||
expect(list.toArray().length === 7).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(({ value }) => value === 4);
|
|
||||||
expect(list.toArray().length === 4).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(({ value }) => value === 5);
|
|
||||||
expect(list.toArray().length === 3).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(({ value }) => value === 5);
|
|
||||||
expect(list.toArray().length === 3).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('list can be cleared and re-add entries', () => {
|
|
||||||
const list = getList();
|
|
||||||
|
|
||||||
list.add(8);
|
|
||||||
list.add(9);
|
|
||||||
|
|
||||||
expect(list.toArray().length === 9).toBe(true);
|
|
||||||
|
|
||||||
list.reverseRemoveUntilTrue(() => false);
|
|
||||||
|
|
||||||
expect(list.toArray().length === 0).toBe(true);
|
|
||||||
|
|
||||||
list.add(1);
|
|
||||||
list.add(2);
|
|
||||||
list.add(3);
|
|
||||||
|
|
||||||
expect(list.toArray().length === 3).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should not iterate empty list ', () => {
|
|
||||||
const list = new List();
|
|
||||||
|
|
||||||
let iterateCount = 0;
|
|
||||||
list.iterate(() => {
|
|
||||||
iterateCount++;
|
|
||||||
});
|
|
||||||
expect(iterateCount === 0).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should iterate', () => {
|
|
||||||
const list = getList();
|
|
||||||
|
|
||||||
let iterateCount = 0;
|
|
||||||
list.iterate(({ value }) => {
|
|
||||||
iterateCount++;
|
|
||||||
if (value === 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
expect(iterateCount === 4).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should reverse iterate', () => {
|
|
||||||
const list = getList();
|
|
||||||
|
|
||||||
let iterateCount = 0;
|
|
||||||
list.iterateReverse(({ value }) => {
|
|
||||||
iterateCount++;
|
|
||||||
if (value === 5) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
expect(iterateCount === 5).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should not reverse iterate empty list', () => {
|
|
||||||
const list = new List();
|
|
||||||
|
|
||||||
let iterateCount = 0;
|
|
||||||
list.iterateReverse(() => {
|
|
||||||
iterateCount++;
|
|
||||||
});
|
|
||||||
expect(iterateCount === 0).toBe(true);
|
|
||||||
});
|
|
@ -1,138 +0,0 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
|
||||||
/* eslint-disable max-classes-per-file */
|
|
||||||
|
|
||||||
import { EventEmitter } from 'events';
|
|
||||||
|
|
||||||
class Node<T> {
|
|
||||||
value: T | null;
|
|
||||||
|
|
||||||
prev: Node<T> | null;
|
|
||||||
|
|
||||||
next: Node<T> | null;
|
|
||||||
|
|
||||||
constructor(value: T) {
|
|
||||||
this.value = value;
|
|
||||||
this.next = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
link(next: Node<T>) {
|
|
||||||
this.next = next;
|
|
||||||
next.prev = this;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type IteratorFn<T, U = unknown> = (cursor: Node<T>) => U;
|
|
||||||
|
|
||||||
export default class List<T> extends EventEmitter {
|
|
||||||
private start: Node<T> | null;
|
|
||||||
|
|
||||||
private tail: Node<T> | null;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.start = null;
|
|
||||||
this.tail = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
add(obj: T): Node<T> {
|
|
||||||
const node = new Node(obj);
|
|
||||||
if (this.start) {
|
|
||||||
this.start = node.link(this.start);
|
|
||||||
} else {
|
|
||||||
this.start = node;
|
|
||||||
this.tail = node;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterate(fn: IteratorFn<T>): void {
|
|
||||||
if (!this.start) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let cursor = this.start;
|
|
||||||
while (cursor) {
|
|
||||||
const result = fn(cursor);
|
|
||||||
if (result === false) {
|
|
||||||
cursor = null;
|
|
||||||
} else {
|
|
||||||
cursor = cursor.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterateReverse(fn: IteratorFn<T>): void {
|
|
||||||
if (!this.tail) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let cursor = this.tail;
|
|
||||||
while (cursor) {
|
|
||||||
const result = fn(cursor);
|
|
||||||
if (result === false) {
|
|
||||||
cursor = null;
|
|
||||||
} else {
|
|
||||||
cursor = cursor.prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reverseRemoveUntilTrue(fn: IteratorFn<T, boolean>): void {
|
|
||||||
if (!this.tail) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cursor = this.tail;
|
|
||||||
while (cursor) {
|
|
||||||
const result = fn(cursor);
|
|
||||||
if (result === false && cursor === this.start) {
|
|
||||||
// whole list is removed
|
|
||||||
this.emit('evicted', cursor.value);
|
|
||||||
this.start = null;
|
|
||||||
this.tail = null;
|
|
||||||
// stop iteration
|
|
||||||
cursor = null;
|
|
||||||
} else if (result === true) {
|
|
||||||
// when TRUE, set match as new tail
|
|
||||||
if (cursor !== this.tail) {
|
|
||||||
this.tail = cursor;
|
|
||||||
cursor.next = null;
|
|
||||||
}
|
|
||||||
// stop iteration
|
|
||||||
cursor = null;
|
|
||||||
} else {
|
|
||||||
// evicted
|
|
||||||
this.emit('evicted', cursor.value);
|
|
||||||
// iterate to next
|
|
||||||
cursor = cursor.prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toArray(): T[] {
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
if (this.start) {
|
|
||||||
let cursor = this.start;
|
|
||||||
while (cursor) {
|
|
||||||
result.push(cursor.value);
|
|
||||||
cursor = cursor.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// toArrayReverse () {
|
|
||||||
// const result = [];
|
|
||||||
|
|
||||||
// if (this.tail) {
|
|
||||||
// let cursor = this.tail;
|
|
||||||
// while (cursor) {
|
|
||||||
// result.push(cursor.value);
|
|
||||||
// cursor = cursor.prev;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ import HealthService from './health-service';
|
|||||||
|
|
||||||
import ProjectService from './project-service';
|
import ProjectService from './project-service';
|
||||||
import StateService from './state-service';
|
import StateService from './state-service';
|
||||||
import ClientMetricsService from './client-metrics';
|
import ClientInstanceService from './client-metrics/client-instance-service';
|
||||||
import ClientMetricsServiceV2 from './client-metrics/client-metrics-service-v2';
|
import ClientMetricsServiceV2 from './client-metrics/client-metrics-service-v2';
|
||||||
import TagTypeService from './tag-type-service';
|
import TagTypeService from './tag-type-service';
|
||||||
import TagService from './tag-service';
|
import TagService from './tag-service';
|
||||||
@ -35,7 +35,7 @@ export const createServices = (
|
|||||||
): IUnleashServices => {
|
): IUnleashServices => {
|
||||||
const accessService = new AccessService(stores, config);
|
const accessService = new AccessService(stores, config);
|
||||||
const apiTokenService = new ApiTokenService(stores, config);
|
const apiTokenService = new ApiTokenService(stores, config);
|
||||||
const clientMetricsService = new ClientMetricsService(stores, config);
|
const clientInstanceService = new ClientInstanceService(stores, config);
|
||||||
const clientMetricsServiceV2 = new ClientMetricsServiceV2(stores, config);
|
const clientMetricsServiceV2 = new ClientMetricsServiceV2(stores, config);
|
||||||
const contextService = new ContextService(stores, config);
|
const contextService = new ContextService(stores, config);
|
||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
@ -87,7 +87,7 @@ export const createServices = (
|
|||||||
strategyService,
|
strategyService,
|
||||||
tagTypeService,
|
tagTypeService,
|
||||||
tagService,
|
tagService,
|
||||||
clientMetricsService,
|
clientInstanceService,
|
||||||
clientMetricsServiceV2,
|
clientMetricsServiceV2,
|
||||||
contextService,
|
contextService,
|
||||||
versionService,
|
versionService,
|
||||||
|
@ -5,7 +5,7 @@ import StateService from '../services/state-service';
|
|||||||
import StrategyService from '../services/strategy-service';
|
import StrategyService from '../services/strategy-service';
|
||||||
import TagTypeService from '../services/tag-type-service';
|
import TagTypeService from '../services/tag-type-service';
|
||||||
import TagService from '../services/tag-service';
|
import TagService from '../services/tag-service';
|
||||||
import ClientMetricsService from '../services/client-metrics';
|
import ClientInstanceService from '../services/client-metrics/client-instance-service';
|
||||||
import ContextService from '../services/context-service';
|
import ContextService from '../services/context-service';
|
||||||
import VersionService from '../services/version-service';
|
import VersionService from '../services/version-service';
|
||||||
import { ApiTokenService } from '../services/api-token-service';
|
import { ApiTokenService } from '../services/api-token-service';
|
||||||
@ -29,7 +29,7 @@ export interface IUnleashServices {
|
|||||||
accessService: AccessService;
|
accessService: AccessService;
|
||||||
addonService: AddonService;
|
addonService: AddonService;
|
||||||
apiTokenService: ApiTokenService;
|
apiTokenService: ApiTokenService;
|
||||||
clientMetricsService: ClientMetricsService;
|
clientInstanceService: ClientInstanceService;
|
||||||
clientMetricsServiceV2: ClientMetricsServiceV2;
|
clientMetricsServiceV2: ClientMetricsServiceV2;
|
||||||
contextService: ContextService;
|
contextService: ContextService;
|
||||||
emailService: EmailService;
|
emailService: EmailService;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import dbInit from '../../helpers/database-init';
|
import dbInit, { ITestDb } from '../../helpers/database-init';
|
||||||
import { setupApp } from '../../helpers/test-helper';
|
import { IUnleashTest, setupApp } from '../../helpers/test-helper';
|
||||||
import getLogger from '../../../fixtures/no-logger';
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
import { parseISO } from 'date-fns';
|
|
||||||
|
|
||||||
let app;
|
let app: IUnleashTest;
|
||||||
let db;
|
let db: ITestDb;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('metrics_serial', getLogger);
|
db = await dbInit('metrics_serial', getLogger);
|
||||||
@ -12,45 +11,38 @@ beforeAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await app.services.clientMetricsService.createApplication({
|
await app.services.clientInstanceService.createApplication({
|
||||||
appName: 'demo-app-1',
|
appName: 'demo-app-1',
|
||||||
strategies: ['default'],
|
strategies: ['default'],
|
||||||
|
//@ts-ignore
|
||||||
announced: true,
|
announced: true,
|
||||||
});
|
});
|
||||||
await app.services.clientMetricsService.createApplication({
|
await app.services.clientInstanceService.createApplication({
|
||||||
appName: 'demo-app-2',
|
appName: 'demo-app-2',
|
||||||
strategies: ['default', 'extra'],
|
strategies: ['default', 'extra'],
|
||||||
description: 'hello',
|
description: 'hello',
|
||||||
|
//@ts-ignore
|
||||||
announced: true,
|
announced: true,
|
||||||
});
|
});
|
||||||
await app.services.clientMetricsService.createApplication({
|
await app.services.clientInstanceService.createApplication({
|
||||||
appName: 'deletable-app',
|
appName: 'deletable-app',
|
||||||
strategies: ['default'],
|
strategies: ['default'],
|
||||||
description: 'Some desc',
|
description: 'Some desc',
|
||||||
|
//@ts-ignore
|
||||||
announced: true,
|
announced: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const clientStartedDate = parseISO('2018-01-15T14:35:38.494Z');
|
|
||||||
await db.stores.clientInstanceStore.insert({
|
await db.stores.clientInstanceStore.insert({
|
||||||
appName: 'demo-app-1',
|
appName: 'demo-app-1',
|
||||||
instanceId: 'test-1',
|
instanceId: 'test-1',
|
||||||
strategies: ['default'],
|
|
||||||
started: clientStartedDate,
|
|
||||||
interval: 10,
|
|
||||||
});
|
});
|
||||||
await db.stores.clientInstanceStore.insert({
|
await db.stores.clientInstanceStore.insert({
|
||||||
appName: 'demo-seed-2',
|
appName: 'demo-seed-2',
|
||||||
instanceId: 'test-2',
|
instanceId: 'test-2',
|
||||||
strategies: ['default'],
|
|
||||||
started: clientStartedDate,
|
|
||||||
interval: 10,
|
|
||||||
});
|
});
|
||||||
await db.stores.clientInstanceStore.insert({
|
await db.stores.clientInstanceStore.insert({
|
||||||
appName: 'deletable-app',
|
appName: 'deletable-app',
|
||||||
instanceId: 'inst-1',
|
instanceId: 'inst-1',
|
||||||
strategies: ['default'],
|
|
||||||
started: clientStartedDate,
|
|
||||||
interval: 10,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ function createApp(
|
|||||||
|
|
||||||
const destroy = async () => {
|
const destroy = async () => {
|
||||||
services.versionService.destroy();
|
services.versionService.destroy();
|
||||||
services.clientMetricsService.destroy();
|
services.clientInstanceService.destroy();
|
||||||
services.apiTokenService.destroy();
|
services.apiTokenService.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import ClientMetricsService from '../../../lib/services/client-metrics';
|
import ClientInstanceService from '../../../lib/services/client-metrics/client-instance-service';
|
||||||
import { IClientApp } from '../../../lib/types/model';
|
import { IClientApp } from '../../../lib/types/model';
|
||||||
import { secondsToMilliseconds } from 'date-fns';
|
import { secondsToMilliseconds } from 'date-fns';
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
@ -10,7 +10,7 @@ const { APPLICATION_CREATED } = require('../../../lib/types/events');
|
|||||||
|
|
||||||
let stores;
|
let stores;
|
||||||
let db;
|
let db;
|
||||||
let clientMetricsService;
|
let clientInstanceService;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('client_metrics_service_serial', getLogger);
|
db = await dbInit('client_metrics_service_serial', getLogger);
|
||||||
@ -20,7 +20,7 @@ beforeAll(async () => {
|
|||||||
const bulkInterval = secondsToMilliseconds(0.5);
|
const bulkInterval = secondsToMilliseconds(0.5);
|
||||||
const announcementInterval = secondsToMilliseconds(2);
|
const announcementInterval = secondsToMilliseconds(2);
|
||||||
|
|
||||||
clientMetricsService = new ClientMetricsService(
|
clientInstanceService = new ClientInstanceService(
|
||||||
stores,
|
stores,
|
||||||
{ getLogger, eventBus },
|
{ getLogger, eventBus },
|
||||||
bulkInterval,
|
bulkInterval,
|
||||||
@ -29,7 +29,7 @@ beforeAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await clientMetricsService.destroy();
|
await clientInstanceService.destroy();
|
||||||
await db.destroy();
|
await db.destroy();
|
||||||
});
|
});
|
||||||
test('Apps registered should be announced', async () => {
|
test('Apps registered should be announced', async () => {
|
||||||
@ -54,12 +54,12 @@ test('Apps registered should be announced', async () => {
|
|||||||
description: faker.company.catchPhrase(),
|
description: faker.company.catchPhrase(),
|
||||||
color: faker.internet.color(),
|
color: faker.internet.color(),
|
||||||
};
|
};
|
||||||
await clientMetricsService.registerClient(clientRegistration, '127.0.0.1');
|
await clientInstanceService.registerClient(clientRegistration, '127.0.0.1');
|
||||||
await clientMetricsService.registerClient(differentClient, '127.0.0.1');
|
await clientInstanceService.registerClient(differentClient, '127.0.0.1');
|
||||||
await new Promise((res) => setTimeout(res, 1200));
|
await new Promise((res) => setTimeout(res, 1200));
|
||||||
const first = await stores.clientApplicationsStore.getUnannounced();
|
const first = await stores.clientApplicationsStore.getUnannounced();
|
||||||
expect(first.length).toBe(2);
|
expect(first.length).toBe(2);
|
||||||
await clientMetricsService.registerClient(clientRegistration, '127.0.0.1');
|
await clientInstanceService.registerClient(clientRegistration, '127.0.0.1');
|
||||||
await new Promise((res) => setTimeout(res, secondsToMilliseconds(2)));
|
await new Promise((res) => setTimeout(res, secondsToMilliseconds(2)));
|
||||||
const second = await stores.clientApplicationsStore.getUnannounced();
|
const second = await stores.clientApplicationsStore.getUnannounced();
|
||||||
expect(second.length).toBe(0);
|
expect(second.length).toBe(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user