Skip to content

Commit 73a3419

Browse files
authored
212 socker debounce (#103)
* Debounce socket events emit Visual-Regression-Tracker/Visual-Regression-Tracker#212
1 parent 09ef50b commit 73a3419

13 files changed

+395
-208
lines changed

src/builds/builds.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { ModifyBuildDto } from './dto/build-modify.dto';
2626
@Controller('builds')
2727
@ApiTags('builds')
2828
export class BuildsController {
29-
constructor(private buildsService: BuildsService) { }
29+
constructor(private buildsService: BuildsService) {}
3030

3131
@Get()
3232
@ApiOkResponse({ type: PaginatedBuildDto })

src/builds/builds.service.spec.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const initService = async ({
5757
provide: EventsGateway,
5858
useValue: {
5959
buildUpdated: eventsBuildUpdatedMock,
60-
buildCreated: eventsBuildCreatedMock
60+
buildCreated: eventsBuildCreatedMock,
6161
},
6262
},
6363
{
@@ -286,28 +286,27 @@ describe('BuildsService', () => {
286286
mocked(BuildDto).mockReturnValueOnce(buildDto);
287287
service = await initService({ buildUpdateMock, eventsBuildUpdatedMock });
288288

289-
const result = await service.update(id, { "isRunning": false });
289+
const result = await service.update(id, { isRunning: false });
290290

291291
expect(buildUpdateMock).toHaveBeenCalledWith({
292292
where: { id },
293293
include: {
294294
testRuns: true,
295295
},
296-
data: { "isRunning": false }
296+
data: { isRunning: false },
297297
});
298-
expect(eventsBuildUpdatedMock).toHaveBeenCalledWith(buildDto);
298+
expect(eventsBuildUpdatedMock).toHaveBeenCalledWith(id);
299299
expect(result).toBe(buildDto);
300300
});
301301

302302
it('approve', async () => {
303-
const eventsBuildUpdatedMock = jest.fn();
304303
const buildFindUniqueMock = jest.fn().mockResolvedValueOnce(build);
305304
const testRunApproveMock = jest.fn().mockResolvedValueOnce({
306305
...build.testRuns[0],
307306
status: TestStatus.approved,
308307
});
309308
mocked(BuildDto).mockReturnValueOnce(buildDto);
310-
service = await initService({ eventsBuildUpdatedMock, buildFindUniqueMock, testRunApproveMock });
309+
service = await initService({ buildFindUniqueMock, testRunApproveMock });
311310

312311
await service.approve('someId', true);
313312

@@ -333,6 +332,5 @@ describe('BuildsService', () => {
333332
},
334333
],
335334
});
336-
expect(eventsBuildUpdatedMock).toHaveBeenCalledWith(buildDto);
337335
});
338336
});

src/builds/builds.service.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class BuildsService {
1818
private testRunsService: TestRunsService,
1919
@Inject(forwardRef(() => ProjectsService))
2020
private projectService: ProjectsService
21-
) { }
21+
) {}
2222

2323
async findOne(id: string): Promise<BuildDto> {
2424
return this.prismaService.build
@@ -106,11 +106,10 @@ export class BuildsService {
106106
include: {
107107
testRuns: true,
108108
},
109-
data: modifyBuildDto
109+
data: modifyBuildDto,
110110
});
111-
const buildDto = new BuildDto(build);
112-
this.eventsGateway.buildUpdated(buildDto);
113-
return buildDto;
111+
this.eventsGateway.buildUpdated(id);
112+
return new BuildDto(build);
114113
}
115114

116115
async remove(id: string): Promise<Build> {
@@ -146,8 +145,6 @@ export class BuildsService {
146145
build.testRuns.map((testRun) => this.testRunsService.approve(testRun.id, merge))
147146
);
148147

149-
const buildDto = new BuildDto(build);
150-
this.eventsGateway.buildUpdated(buildDto);
151-
return buildDto;
148+
return new BuildDto(build);
152149
}
153150
}

src/builds/dto/build.dto.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export class BuildDto {
6464
// calculate statistics
6565
build.testRuns.forEach((testRun) => {
6666
switch (testRun.status) {
67+
case TestStatus.autoApproved:
6768
case TestStatus.approved:
6869
case TestStatus.ok: {
6970
this.passedCount += 1;
Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,112 @@
11
import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
22
import { Server } from 'socket.io';
3-
import { TestRun } from '@prisma/client';
3+
import { Build, TestRun } from '@prisma/client';
44
import { BuildDto } from '../../builds/dto/build.dto';
5+
import { debounce } from 'lodash';
6+
import { PrismaService } from '../../prisma/prisma.service';
57

68
@WebSocketGateway()
79
export class EventsGateway {
810
@WebSocketServer()
911
server: Server;
1012

13+
constructor(private prismaService: PrismaService) {}
14+
15+
private debounceTimeout = 1500;
16+
private maxWait = 3000;
17+
private testRunsCreatedQueued: Array<TestRun> = [];
18+
private testRunsDeletedQueued: Array<TestRun> = [];
19+
private testRunsUpdatedQueued: Array<TestRun> = [];
20+
private buildsUpdatedQueued: Array<string> = [];
21+
1122
buildCreated(build: BuildDto): void {
1223
this.server.emit('build_created', build);
1324
}
1425

15-
buildUpdated(build: BuildDto): void {
16-
this.server.emit('build_updated', build);
26+
buildUpdated(id: string): void {
27+
this.buildsUpdatedQueued.push(id);
28+
this.buildUpdatedDebounced();
1729
}
1830

1931
testRunCreated(testRun: TestRun): void {
20-
this.server.emit('testRun_created', testRun);
32+
this.testRunsCreatedQueued.push(testRun);
33+
this.testRunCreatedDebounced();
34+
this.buildUpdated(testRun.buildId);
2135
}
2236

2337
testRunUpdated(testRun: TestRun): void {
24-
this.server.emit('testRun_updated', testRun);
38+
this.testRunsUpdatedQueued.push(testRun);
39+
this.testRunUpdatedDebounced();
40+
this.buildUpdated(testRun.buildId);
2541
}
2642

2743
testRunDeleted(testRun: TestRun): void {
28-
this.server.emit('testRun_deleted', testRun);
44+
this.testRunsDeletedQueued.push(testRun);
45+
this.testRunDeletedDebounced();
46+
this.buildUpdated(testRun.buildId);
2947
}
48+
49+
private testRunUpdatedDebounced = debounce(
50+
() => {
51+
this.server.emit('testRun_updated', this.testRunsUpdatedQueued);
52+
this.testRunsUpdatedQueued = [];
53+
},
54+
this.debounceTimeout,
55+
{
56+
leading: true,
57+
maxWait: this.maxWait,
58+
}
59+
);
60+
61+
private testRunCreatedDebounced = debounce(
62+
() => {
63+
this.server.emit('testRun_created', this.testRunsCreatedQueued);
64+
this.testRunsCreatedQueued = [];
65+
},
66+
this.debounceTimeout,
67+
{
68+
leading: true,
69+
maxWait: this.maxWait,
70+
}
71+
);
72+
73+
private testRunDeletedDebounced = debounce(
74+
() => {
75+
this.server.emit('testRun_deleted', this.testRunsDeletedQueued);
76+
this.testRunsDeletedQueued = [];
77+
},
78+
this.debounceTimeout,
79+
{
80+
leading: true,
81+
maxWait: this.maxWait,
82+
}
83+
);
84+
85+
private buildUpdatedDebounced = debounce(
86+
() => {
87+
this.prismaService.build
88+
.findMany({
89+
where: {
90+
id: {
91+
in: this.buildsUpdatedQueued,
92+
},
93+
},
94+
include: {
95+
testRuns: true,
96+
},
97+
})
98+
.then((builds: Array<Build>) => {
99+
this.server.emit(
100+
'build_updated',
101+
builds.map((build: Build) => new BuildDto(build))
102+
);
103+
});
104+
this.buildsUpdatedQueued = [];
105+
},
106+
this.debounceTimeout,
107+
{
108+
leading: true,
109+
maxWait: this.maxWait,
110+
}
111+
);
30112
}

src/shared/shared.module.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Global, Module } from '@nestjs/common';
22
import { StaticService } from './static/static.service';
33
import { EventsGateway } from '../shared/events/events.gateway';
4+
import { PrismaService } from '../prisma/prisma.service';
45

56
@Global()
67
@Module({
7-
providers: [StaticService, EventsGateway],
8-
exports: [StaticService, EventsGateway],
9-
imports: [],
10-
controllers: [],
8+
providers: [StaticService, EventsGateway, PrismaService],
9+
exports: [StaticService, EventsGateway, PrismaService],
10+
imports: [],
11+
controllers: [],
1112
})
12-
export class SharedModule {}
13+
export class SharedModule {}

src/test-runs/test-runs.controller.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ export class TestRunsController {
3636
return this.testRunsService.findMany(buildId);
3737
}
3838

39-
@Get('recalculateDiff/:id')
40-
@ApiParam({ name: 'id', required: true })
41-
@ApiBearerAuth()
42-
@UseGuards(JwtAuthGuard)
43-
recalculateDiff(@Param('id', new ParseUUIDPipe()) id: string): Promise<TestRun> {
44-
return this.testRunsService.recalculateDiff(id);
45-
}
46-
4739
@Get('approve')
4840
@ApiQuery({ name: 'id', required: true })
4941
@ApiQuery({ name: 'merge', required: false })

0 commit comments

Comments
 (0)