mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-09 11:14:29 +02:00
fix: count events instead of loading them in memory (#3382)
Refactor project events to use count instead of loading the events in memory
This commit is contained in:
parent
30c1ebc3c3
commit
354e54a356
@ -207,6 +207,35 @@ class EventStore implements IEventStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async queryCount(operations: IQueryOperations[]): Promise<number> {
|
||||||
|
try {
|
||||||
|
let query: Knex.QueryBuilder = this.db.count().from(TABLE);
|
||||||
|
|
||||||
|
operations.forEach((operation) => {
|
||||||
|
if (operation.op === 'where') {
|
||||||
|
query = this.where(query, operation.parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.op === 'forFeatures') {
|
||||||
|
query = this.forFeatures(query, operation.parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.op === 'beforeDate') {
|
||||||
|
query = this.beforeDate(query, operation.parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.op === 'betweenDate') {
|
||||||
|
query = this.betweenDate(query, operation.parameters);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const queryResult = await query.first();
|
||||||
|
return parseInt(queryResult.count || 0);
|
||||||
|
} catch (e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
where(
|
where(
|
||||||
query: Knex.QueryBuilder,
|
query: Knex.QueryBuilder,
|
||||||
parameters: { [key: string]: string },
|
parameters: { [key: string]: string },
|
||||||
|
@ -43,7 +43,7 @@ async function createApp(
|
|||||||
const db = createDb(config);
|
const db = createDb(config);
|
||||||
const stores = createStores(config, db);
|
const stores = createStores(config, db);
|
||||||
const services = createServices(stores, config, db);
|
const services = createServices(stores, config, db);
|
||||||
scheduleServices(services, config);
|
scheduleServices(services);
|
||||||
|
|
||||||
const metricsMonitor = createMetricsMonitor();
|
const metricsMonitor = createMetricsMonitor();
|
||||||
const unleashSession = sessionDb(config, db);
|
const unleashSession = sessionDb(config, db);
|
||||||
|
@ -58,10 +58,7 @@ import {
|
|||||||
} from '../features/change-request-access-service/createChangeRequestAccessReadModel';
|
} from '../features/change-request-access-service/createChangeRequestAccessReadModel';
|
||||||
|
|
||||||
// TODO: will be moved to scheduler feature directory
|
// TODO: will be moved to scheduler feature directory
|
||||||
export const scheduleServices = (
|
export const scheduleServices = (services: IUnleashServices): void => {
|
||||||
services: IUnleashServices,
|
|
||||||
config: IUnleashConfig,
|
|
||||||
): void => {
|
|
||||||
const {
|
const {
|
||||||
schedulerService,
|
schedulerService,
|
||||||
apiTokenService,
|
apiTokenService,
|
||||||
@ -94,12 +91,10 @@ export const scheduleServices = (
|
|||||||
hoursToMilliseconds(24),
|
hoursToMilliseconds(24),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (config.flagResolver.isEnabled('projectStatusApi')) {
|
|
||||||
schedulerService.schedule(
|
schedulerService.schedule(
|
||||||
projectService.statusJob.bind(projectService),
|
projectService.statusJob.bind(projectService),
|
||||||
hoursToMilliseconds(24),
|
hoursToMilliseconds(24),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
schedulerService.schedule(
|
schedulerService.schedule(
|
||||||
projectHealthService.setHealthRating.bind(projectHealthService),
|
projectHealthService.setHealthRating.bind(projectHealthService),
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
ProjectUserRemovedEvent,
|
ProjectUserRemovedEvent,
|
||||||
ProjectUserUpdateRoleEvent,
|
ProjectUserUpdateRoleEvent,
|
||||||
RoleName,
|
RoleName,
|
||||||
|
IFlagResolver,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import {
|
||||||
IProjectQuery,
|
IProjectQuery,
|
||||||
@ -114,6 +115,8 @@ export default class ProjectService {
|
|||||||
|
|
||||||
private projectStatsStore: IProjectStatsStore;
|
private projectStatsStore: IProjectStatsStore;
|
||||||
|
|
||||||
|
private flagResolver: IFlagResolver;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
projectStore,
|
projectStore,
|
||||||
@ -157,6 +160,7 @@ export default class ProjectService {
|
|||||||
this.groupService = groupService;
|
this.groupService = groupService;
|
||||||
this.projectStatsStore = projectStatsStore;
|
this.projectStatsStore = projectStatsStore;
|
||||||
this.logger = config.getLogger('services/project-service.js');
|
this.logger = config.getLogger('services/project-service.js');
|
||||||
|
this.flagResolver = config.flagResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjects(
|
async getProjects(
|
||||||
@ -664,6 +668,7 @@ export default class ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async statusJob(): Promise<void> {
|
async statusJob(): Promise<void> {
|
||||||
|
if (this.flagResolver.isEnabled('projectStatusApi')) {
|
||||||
const projects = await this.store.getAll();
|
const projects = await this.store.getAll();
|
||||||
|
|
||||||
const statusUpdates = await Promise.all(
|
const statusUpdates = await Promise.all(
|
||||||
@ -678,6 +683,9 @@ export default class ProjectService {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
this.logger.info('Project status API is disabled');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStatusUpdates(projectId: string): Promise<ICalculateStatus> {
|
async getStatusUpdates(projectId: string): Promise<ICalculateStatus> {
|
||||||
@ -726,7 +734,7 @@ export default class ProjectService {
|
|||||||
|
|
||||||
const [projectActivityCurrentWindow, projectActivityPastWindow] =
|
const [projectActivityCurrentWindow, projectActivityPastWindow] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.eventStore.query([
|
this.eventStore.queryCount([
|
||||||
{ op: 'where', parameters: { project: projectId } },
|
{ op: 'where', parameters: { project: projectId } },
|
||||||
{
|
{
|
||||||
op: 'beforeDate',
|
op: 'beforeDate',
|
||||||
@ -736,7 +744,7 @@ export default class ProjectService {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
this.eventStore.query([
|
this.eventStore.queryCount([
|
||||||
{ op: 'where', parameters: { project: projectId } },
|
{ op: 'where', parameters: { project: projectId } },
|
||||||
{
|
{
|
||||||
op: 'betweenDate',
|
op: 'betweenDate',
|
||||||
@ -792,9 +800,8 @@ export default class ProjectService {
|
|||||||
createdPastWindow: createdPastWindow.length,
|
createdPastWindow: createdPastWindow.length,
|
||||||
archivedCurrentWindow: archivedCurrentWindow.length,
|
archivedCurrentWindow: archivedCurrentWindow.length,
|
||||||
archivedPastWindow: archivedPastWindow.length,
|
archivedPastWindow: archivedPastWindow.length,
|
||||||
projectActivityCurrentWindow:
|
projectActivityCurrentWindow: projectActivityCurrentWindow,
|
||||||
projectActivityCurrentWindow.length,
|
projectActivityPastWindow: projectActivityPastWindow,
|
||||||
projectActivityPastWindow: projectActivityPastWindow.length,
|
|
||||||
projectMembersAddedCurrentWindow:
|
projectMembersAddedCurrentWindow:
|
||||||
projectMembersAddedCurrentWindow,
|
projectMembersAddedCurrentWindow,
|
||||||
},
|
},
|
||||||
|
@ -15,4 +15,5 @@ export interface IEventStore
|
|||||||
searchEvents(search: SearchEventsSchema): Promise<IEvent[]>;
|
searchEvents(search: SearchEventsSchema): Promise<IEvent[]>;
|
||||||
getMaxRevisionId(currentMax?: number): Promise<number>;
|
getMaxRevisionId(currentMax?: number): Promise<number>;
|
||||||
query(operations: IQueryOperations[]): Promise<IEvent[]>;
|
query(operations: IQueryOperations[]): Promise<IEvent[]>;
|
||||||
|
queryCount(operations: IQueryOperations[]): Promise<number>;
|
||||||
}
|
}
|
||||||
|
@ -1390,4 +1390,6 @@ test('should get correct amount of project members for current and past window',
|
|||||||
|
|
||||||
const result = await projectService.getStatusUpdates(project.id);
|
const result = await projectService.getStatusUpdates(project.id);
|
||||||
expect(result.updates.projectMembersAddedCurrentWindow).toBe(5);
|
expect(result.updates.projectMembersAddedCurrentWindow).toBe(5);
|
||||||
|
expect(result.updates.projectActivityCurrentWindow).toBe(6);
|
||||||
|
expect(result.updates.projectActivityPastWindow).toBe(0);
|
||||||
});
|
});
|
||||||
|
5
src/test/fixtures/fake-event-store.ts
vendored
5
src/test/fixtures/fake-event-store.ts
vendored
@ -95,6 +95,11 @@ class FakeEventStore implements IEventStore {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async queryCount(operations: IQueryOperations[]): Promise<number> {
|
||||||
|
if (operations) return 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
setMaxListeners(number: number): EventEmitter {
|
setMaxListeners(number: number): EventEmitter {
|
||||||
return this.eventEmitter.setMaxListeners(number);
|
return this.eventEmitter.setMaxListeners(number);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user