Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/event-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export abstract class EventWorker extends Worker {
catcherType: this.type as CatcherMessageType,
payload: task.payload as CatcherMessagePayload<ErrorsCatcherType>,
timestamp: task.timestamp,
count: task.count,
} as GroupWorkerTask<ErrorsCatcherType>);
}

Expand Down
13 changes: 13 additions & 0 deletions lib/types/hawk-types-augmentation.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { CatcherMessageType } from '@hawk.so/types';

// TODO: delete this file once the @hawk.so/types dependency is bumped past that release
declare module '@hawk.so/types' {
// eslint-disable-next-line @typescript-eslint/no-shadow, @typescript-eslint/naming-convention, no-unused-vars, @typescript-eslint/no-unused-vars
interface CatcherMessage<_Type extends CatcherMessageType> {
count?: number;
}

interface RepetitionDBScheme {
count?: number;
}
}
29 changes: 21 additions & 8 deletions workers/grouper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export default class GrouperWorker extends Worker {
*/
await this.saveEvent(task.projectId, {
groupHash: uniqueEventHash,
totalCount: 1,
totalCount: task.count ?? 1,
catcherType: task.catcherType,
payload: task.payload,
timestamp: task.timestamp,
Expand Down Expand Up @@ -297,7 +297,7 @@ export default class GrouperWorker extends Worker {
*/
await this.incrementEventCounterAndAffectedUsers(task.projectId, {
groupHash: uniqueEventHash,
}, incrementAffectedUsers);
}, incrementAffectedUsers, task.count ?? 1);

/**
* Decode existed event to calculate diffs correctly
Expand Down Expand Up @@ -333,6 +333,15 @@ export default class GrouperWorker extends Worker {
timestamp: task.timestamp,
} as RepetitionDBScheme;

/**
* Store count only when it carries information (>1)
* Absent or 1 both mean "single occurrence",
* so omitting it keeps repetition documents lean.
*/
if (task.count !== undefined && task.count > 1) {
newRepetition.count = task.count;
}

repetitionId = await this.saveRepetition(task.projectId, newRepetition);

/**
Expand All @@ -355,7 +364,8 @@ export default class GrouperWorker extends Worker {
uniqueEventHash,
task.timestamp,
repetitionId,
incrementDailyAffectedUsers
incrementDailyAffectedUsers,
task.count ?? 1
);

this.memoryMonitor.logHandleCompletion(
Expand Down Expand Up @@ -768,8 +778,9 @@ export default class GrouperWorker extends Worker {
* @param projectId - project id to increment
* @param query - query to get event
* @param incrementAffected - if true, usersAffected counter will be incremented
* @param incrementBy - how many occurrences this repetition represents
*/
private async incrementEventCounterAndAffectedUsers(projectId, query, incrementAffected: boolean): Promise<number> {
private async incrementEventCounterAndAffectedUsers(projectId, query, incrementAffected: boolean, incrementBy = 1): Promise<number> {
if (!projectId || !mongodb.ObjectID.isValid(projectId)) {
throw new ValidationError('Controller.saveEvent: Project ID is invalid or missed');
}
Expand All @@ -779,13 +790,13 @@ export default class GrouperWorker extends Worker {
const updateQuery = incrementAffected
? {
$inc: {
totalCount: 1,
totalCount: incrementBy,
usersAffected: 1,
},
}
: {
$inc: {
totalCount: 1,
totalCount: incrementBy,
},
};

Expand All @@ -806,14 +817,16 @@ export default class GrouperWorker extends Worker {
* @param {string} eventTimestamp - timestamp of the last event
* @param {string|null} repetitionId - event's last repetition id
* @param {boolean} shouldIncrementAffectedUsers - whether to increment affected users
* @param {number} incrementBy - how many occurrences this task represents
* @returns {Promise<void>}
*/
private async saveDailyEvents(
projectId: string,
eventHash: string,
eventTimestamp: number,
repetitionId: string | null,
shouldIncrementAffectedUsers: boolean
shouldIncrementAffectedUsers: boolean,
incrementBy = 1
): Promise<void> {
if (!projectId || !mongodb.ObjectID.isValid(projectId)) {
throw new ValidationError('GrouperWorker.saveDailyEvents: Project ID is invalid or missed');
Expand All @@ -838,7 +851,7 @@ export default class GrouperWorker extends Worker {
lastRepetitionId: repetitionId,
},
$inc: {
count: 1,
count: incrementBy,
affectedUsers: shouldIncrementAffectedUsers ? 1 : 0,
},
},
Expand Down
51 changes: 50 additions & 1 deletion workers/grouper/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ const projectMock = {
*
* @param event - allows to override some event properties in generated task
* @param timestamp - timestamp of the event, defaults to current time
* @param count - number of occurrences this task represents
*/
function generateTask(event: Partial<EventData<EventAddons>> = undefined, timestamp: number = new Date().getTime()): GroupWorkerTask<ErrorsCatcherType> {
function generateTask(event: Partial<EventData<EventAddons>> = undefined, timestamp: number = new Date().getTime(), count: number = undefined): GroupWorkerTask<ErrorsCatcherType> {
return {
projectId: projectIdMock,
catcherType: 'errors/javascript',
timestamp,
count,
payload: Object.assign({
title: 'Hawk client catcher test',
backtrace: [],
Expand Down Expand Up @@ -182,6 +184,19 @@ describe('GrouperWorker', () => {
expect((await eventsCollection.findOne({})).totalCount).toBe(4);
});

test('Should set total events count to repetition count on first occurrence when count is provided', async () => {
await worker.handle(generateTask(undefined, undefined, 5));

expect((await eventsCollection.findOne({})).totalCount).toBe(5);
});

test('Should increment total events count by repetition count on processing when count is provided', async () => {
await worker.handle(generateTask(undefined, undefined, 3));
await worker.handle(generateTask(undefined, undefined, 2));

expect((await eventsCollection.findOne({})).totalCount).toBe(5);
});

test('Should not increment total usersAffected count if it is event from first user', async () => {
await worker.handle(generateTask({ user: { id: '123' } }));
await worker.handle(generateTask({ user: { id: '123' } }));
Expand Down Expand Up @@ -351,6 +366,13 @@ describe('GrouperWorker', () => {
expect((await dailyEventsCollection.findOne({})).count).toBe(4);
});

test('Should update events count per day by repetition count', async () => {
await worker.handle(generateTask(undefined, undefined, 3));
await worker.handle(generateTask(undefined, undefined, 2));

expect((await dailyEventsCollection.findOne({})).count).toBe(5);
});

test('Should update last repetition id', async () => {
await worker.handle(generateTask());
await worker.handle(generateTask());
Expand All @@ -374,6 +396,33 @@ describe('GrouperWorker', () => {
}).toArray()).length).toBe(2);
});

test('Should save repetition count when count is greater than 1', async () => {
await worker.handle(generateTask());
await worker.handle(generateTask(undefined, undefined, 7));

const savedRepetition = await repetitionsCollection.findOne({});

expect(savedRepetition.count).toBe(7);
});

test('Should omit repetition count when count is absent', async () => {
await worker.handle(generateTask());
await worker.handle(generateTask());

const savedRepetition = await repetitionsCollection.findOne({});

expect(savedRepetition.count).toBeUndefined();
});

test('Should omit repetition count when count is exactly 1', async () => {
await worker.handle(generateTask());
await worker.handle(generateTask(undefined, undefined, 1));

const savedRepetition = await repetitionsCollection.findOne({});

expect(savedRepetition.count).toBeUndefined();
});

test('Should stringify delta', async () => {
const generatedTask = generateTask();

Expand Down
1 change: 1 addition & 0 deletions workers/javascript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export default class JavascriptEventWorker extends EventWorker {
catcherType: this.type as CatcherMessageType,
payload: event.payload as CatcherMessagePayload<CatcherMessageType>,
timestamp: event.timestamp,
count: event.count,
} as GroupWorkerTask<ErrorsCatcherType>);
}

Expand Down
Loading