Skip to content

Commit f8764b9

Browse files
author
Przybylski Krzysztof
committed
fix: optimize builds service
1 parent b6fb5a1 commit f8764b9

File tree

4 files changed

+65
-30
lines changed

4 files changed

+65
-30
lines changed

src/builds/builds.controller.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe('Builds Controller', () => {
7878
const result = await controller.create(createBuildDto);
7979

8080
expect(result).toStrictEqual(new BuildDto(buildWithNumber));
81-
expect(deleteOldBuilds).toHaveBeenCalledWith(project.id, project.maxBuildAllowed);
81+
expect(deleteOldBuilds).toHaveBeenCalledWith(project);
8282
});
8383

8484
it('should reuse build', async () => {

src/builds/builds.service.spec.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { BuildDto } from './dto/build.dto';
99
import { ProjectsService } from '../projects/projects.service';
1010
import { generateTestRun } from '../_data_';
1111
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
12+
import { StaticService } from '../static/static.service';
1213

1314
jest.mock('./dto/build.dto');
1415

@@ -23,11 +24,15 @@ const initService = async ({
2324
testRunDeleteMock = jest.fn(),
2425
testRunApproveMock = jest.fn(),
2526
testRunFindManyMock = jest.fn(),
27+
testRunDeleteManyMock = jest.fn(),
2628
eventsBuildUpdatedMock = jest.fn(),
2729
eventsBuildCreatedMock = jest.fn(),
2830
eventBuildDeletedMock = jest.fn(),
2931
projectFindOneMock = jest.fn(),
3032
projectUpdateMock = jest.fn(),
33+
getImageMock = jest.fn(),
34+
saveImageMock = jest.fn(),
35+
deleteImageMock = jest.fn(),
3136
}) => {
3237
const module: TestingModule = await Test.createTestingModule({
3338
providers: [
@@ -47,6 +52,10 @@ const initService = async ({
4752
upsert: buildUpsertMock,
4853
count: buildCountMock,
4954
},
55+
testRun: {
56+
findMany: testRunFindManyMock.mockResolvedValue([]),
57+
deleteMany: testRunDeleteManyMock,
58+
},
5059
},
5160
},
5261
{
@@ -71,6 +80,14 @@ const initService = async ({
7180
findOne: projectFindOneMock,
7281
},
7382
},
83+
{
84+
provide: StaticService,
85+
useValue: {
86+
getImage: getImageMock,
87+
saveImage: saveImageMock,
88+
deleteImage: deleteImageMock,
89+
},
90+
},
7491
],
7592
}).compile();
7693

@@ -142,6 +159,9 @@ describe('BuildsService', () => {
142159
skip: 20,
143160
orderBy: { createdAt: 'desc' },
144161
where: { projectId },
162+
include: {
163+
testRuns: true,
164+
},
145165
});
146166
expect(result).toEqual({
147167
data: [buildDto],
@@ -155,12 +175,12 @@ describe('BuildsService', () => {
155175
const buildFindUniqueMock = jest.fn().mockResolvedValueOnce(build);
156176
const buildFindManyMock = jest.fn().mockImplementation(() => Promise.resolve(build));
157177
const buildDeleteMock = jest.fn().mockImplementation(() => Promise.resolve(build));
158-
const testRunDeleteMock = jest.fn();
178+
const testRunDeleteManyMock = jest.fn();
159179
const eventBuildDeletedMock = jest.fn();
160180
service = await initService({
161181
buildFindUniqueMock,
162182
buildDeleteMock,
163-
testRunDeleteMock,
183+
testRunDeleteManyMock,
164184
eventBuildDeletedMock,
165185
buildFindManyMock,
166186
});
@@ -173,7 +193,7 @@ describe('BuildsService', () => {
173193
testRuns: true,
174194
},
175195
});
176-
expect(testRunDeleteMock).toHaveBeenCalledWith(build.testRuns[0].id);
196+
expect(testRunDeleteManyMock).toHaveBeenCalledWith({ where: { buildId: { in: [build.id] } } });
177197
expect(eventBuildDeletedMock).toHaveBeenCalledWith(new BuildDto(build));
178198
expect(buildDeleteMock).toHaveBeenCalledWith({
179199
where: { id: build.id },

src/builds/builds.service.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,13 @@ export class BuildsService {
2121
) {}
2222

2323
async findOne(id: string): Promise<BuildDto> {
24-
const [build, testRuns] = await Promise.all([
25-
this.prismaService.build.findUnique({
26-
where: { id },
27-
}),
28-
this.testRunsService.findMany(id),
29-
]);
30-
return new BuildDto({
31-
...build,
32-
testRuns,
24+
const build = await this.prismaService.build.findUnique({
25+
where: { id },
26+
include: {
27+
testRuns: true,
28+
},
3329
});
30+
return new BuildDto(build);
3431
}
3532

3633
async findMany(projectId: string, take: number, skip: number): Promise<PaginatedBuildDto> {
@@ -41,11 +38,12 @@ export class BuildsService {
4138
take,
4239
skip,
4340
orderBy: { createdAt: 'desc' },
41+
include: { testRuns: true },
4442
}),
4543
]);
4644

4745
return {
48-
data: await Promise.all(buildList.map((build) => this.findOne(build.id))),
46+
data: buildList.map((build) => new BuildDto(build)),
4947
total,
5048
take,
5149
skip,
@@ -76,7 +74,7 @@ export class BuildsService {
7674
return;
7775
}
7876

79-
await Promise.all(build.testRuns.map((testRun) => this.testRunsService.delete(testRun.id)));
77+
await this.deleteBulkTestRuns([build.id]);
8078

8179
try {
8280
await this.prismaService.build.delete({ where: { id } });
@@ -95,19 +93,7 @@ export class BuildsService {
9593
return build;
9694
}
9795

98-
async deleteOldBuilds(project: Project) {
99-
this.logger.log('Going to delete old builds');
100-
101-
const keepBuilds = project.maxBuildAllowed <= 1 ? 1 : project.maxBuildAllowed - 1;
102-
103-
const buildsToDelete = await this.prismaService.build.findMany({
104-
where: { projectId: { equals: project.id } },
105-
orderBy: { createdAt: 'desc' },
106-
skip: keepBuilds,
107-
});
108-
109-
const buildIds = buildsToDelete.map((build) => build.id);
110-
96+
async deleteBulkTestRuns(buildIds: string[]) {
11197
const testRunsToDelete = await this.prismaService.testRun.findMany({ where: { buildId: { in: buildIds } } });
11298

11399
await this.prismaService.testRun.deleteMany({ where: { buildId: { in: buildIds } } });
@@ -121,6 +107,22 @@ export class BuildsService {
121107
this.logger.log(`TestRun deleted ${testRun.id}`);
122108
this.eventsGateway.testRunDeleted(testRun);
123109
});
110+
}
111+
112+
async deleteOldBuilds(project: Project) {
113+
this.logger.log('Going to delete old builds');
114+
115+
const keepBuilds = project.maxBuildAllowed <= 1 ? 1 : project.maxBuildAllowed - 1;
116+
117+
const buildsToDelete = await this.prismaService.build.findMany({
118+
where: { projectId: { equals: project.id } },
119+
orderBy: { createdAt: 'desc' },
120+
skip: keepBuilds,
121+
});
122+
123+
const buildIds = buildsToDelete.map((build) => build.id);
124+
125+
await this.deleteBulkTestRuns(buildIds);
124126

125127
await this.prismaService.build.deleteMany({ where: { id: { in: buildIds } } });
126128

test/builds.e2e-spec.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { TestRunsService } from '../src/test-runs/test-runs.service';
1212
import { BuildsController } from '../src/builds/builds.controller';
1313
import { TEST_PROJECT } from '../src/_data_';
1414
import uuidAPIKey from 'uuid-apikey';
15+
import { readFileSync } from 'fs';
1516

1617
describe('Builds (e2e)', () => {
1718
let app: INestApplication;
@@ -65,8 +66,20 @@ describe('Builds (e2e)', () => {
6566
branchName: `branchName-${count}`,
6667
project: project.id,
6768
};
68-
await requestWithApiKey(app, 'post', '/builds', user.apiKey).send(createBuildDto).expect(201);
69-
await haveTestRunCreated(buildsService, testRunsService, project.id, `branchName-${count}`, image_v1);
69+
70+
const buildId = (await requestWithApiKey(app, 'post', '/builds', user.apiKey).send(createBuildDto).expect(201))
71+
.body.id;
72+
73+
await testRunsService.postTestRun({
74+
createTestRequestDto: {
75+
projectId: project.id,
76+
branchName: `branchName-${count}`,
77+
buildId,
78+
name: 'Image name',
79+
merge: false,
80+
},
81+
imageBuffer: readFileSync(image_v1),
82+
});
7083
};
7184

7285
for (let i = 0; i < 6; i++) {

0 commit comments

Comments
 (0)