From ed7f01fa204be1aa8d963235c5662852a16d9963 Mon Sep 17 00:00:00 2001 From: Nico Jensch Date: Wed, 6 Nov 2024 18:20:09 +0100 Subject: [PATCH] feat(backend): bring new query routes --- backend/src/builder/builder.controller.ts | 53 +++++++---- backend/src/builder/builder.service.ts | 89 +++++++++++++++++++ .../src/repo-manager/repo-manager.service.ts | 4 +- 3 files changed, 128 insertions(+), 18 deletions(-) diff --git a/backend/src/builder/builder.controller.ts b/backend/src/builder/builder.controller.ts index 7d83c2f7..b725be2a 100644 --- a/backend/src/builder/builder.controller.ts +++ b/backend/src/builder/builder.controller.ts @@ -10,19 +10,19 @@ export class BuilderController { @AllowAnonymous() @Get("builders") async getBuilders(): Promise { - return this.builderService.getBuilders(); + return await this.builderService.getBuilders(); } @AllowAnonymous() @Get("packages") async getPackages(): Promise { - return this.builderService.getPackages(); + return await this.builderService.getPackages(); } @AllowAnonymous() @Get("repos") async getRepos(): Promise { - return this.builderService.getRepos(); + return await this.builderService.getRepos(); } @AllowAnonymous() @@ -32,7 +32,7 @@ export class BuilderController { @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, @Query("amount", new ParseIntPipe({ optional: true })) amount = 50, ): Promise { - return this.builderService.getBuilds({ builder, offset, amount }); + return await this.builderService.getBuilds({ builder, offset, amount }); } @AllowAnonymous() @@ -41,7 +41,7 @@ export class BuilderController { @Query("amount", new ParseIntPipe({ optional: true })) amount = 50, @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, ): Promise { - return this.builderService.getLastBuilds({ amount, offset }); + return await this.builderService.getLastBuilds({ amount, offset }); } @AllowAnonymous() @@ -51,7 +51,7 @@ export class BuilderController { @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, @Query("amount", new ParseIntPipe({ optional: true })) amount = 30, ): Promise { - return this.builderService.getLastBuildsForPackage({ pkgname, amount, offset }); + return await this.builderService.getLastBuildsForPackage({ pkgname, amount, offset }); } @AllowAnonymous() @@ -61,14 +61,13 @@ export class BuilderController { @Param("days", ParseIntPipe) days: number, @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, ): Promise { - return this.builderService.getLastBuildsForPackage({ pkgname, amount: days, offset }); + return await this.builderService.getLastBuildsForPackage({ pkgname, amount: days, offset }); } @AllowAnonymous() @Get("count/days") - async getBuildsPerPackage( - ): Promise<{ pkgbase: string; count: string }[]> { - return this.builderService.getBuildsPerPackage(); + async getBuildsPerPackage(): Promise<{ pkgbase: string; count: string }[]> { + return await this.builderService.getBuildsPerPackage(); } @AllowAnonymous() @@ -76,13 +75,13 @@ export class BuilderController { async getBuildsPerPackageWithDays( @Param("days", ParseIntPipe) days: number, ): Promise<{ pkgbase: string; count: string }[]> { - return this.builderService.getBuildsPerPackage({ days }); + return await this.builderService.getBuildsPerPackage({ days }); } @AllowAnonymous() @Get("count/package/:pkgname") async getLatestBuildsCountByPkgname(@Param("pkgname") pkgname: string): Promise { - return this.builderService.getLastBuildsCountForPackage(pkgname); + return await this.builderService.getLastBuildsCountForPackage(pkgname); } @AllowAnonymous() @@ -92,7 +91,7 @@ export class BuilderController { @Param("amount", new ParseIntPipe({ optional: true })) amount = 50, @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, ): Promise<{ day: string; count: string }[]> { - return this.builderService.getBuildsCountByPkgnamePerDay({ pkgname, amount, offset }); + return await this.builderService.getBuildsCountByPkgnamePerDay({ pkgname, amount, offset }); } @AllowAnonymous() @@ -102,7 +101,7 @@ export class BuilderController { @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, @Query("status", new ParseIntPipe({ optional: true })) status?: number, ): Promise<{ pkgname: string; count: string }[]> { - return this.builderService.getPopularPackages({ amount, offset, status }); + return await this.builderService.getPopularPackages({ amount, offset, status }); } /** @@ -111,7 +110,7 @@ export class BuilderController { @AllowAnonymous() @Get("builders/amount") async getBuildersAmount(): Promise<{ builderId: string; count: string }[]> { - return this.builderService.getBuildsPerBuilder(); + return await this.builderService.getBuildsPerBuilder(); } @AllowAnonymous() @@ -126,12 +125,32 @@ export class BuilderController { count: string; }[] > { - return this.builderService.getBuildsCountByPkgnamePerDay({ offset, pkgname, amount: days }); + return await this.builderService.getBuildsCountByPkgnamePerDay({ offset, pkgname, amount: days }); } @AllowAnonymous() @Get("per-day/:days") async getBuildsPerDay(@Param("days", ParseIntPipe) days: number): Promise<{ day: string; count: string }[]> { - return this.builderService.getBuildsPerDay({ days: days }); + return await this.builderService.getBuildsPerDay({ days: days }); + } + + @AllowAnonymous() + @Get("latest/url/:amount") + async getLatestBuildsByPkgnameWithUrls( + @Param("amount", new ParseIntPipe({ optional: true })) amount = 50, + @Query("offset", new ParseIntPipe({ optional: true })) offset = 0, + ): Promise<{ commit: string; logUrl: string; pkgname: string; timeToEnd: string; version: string }[]> { + return await this.builderService.getLatestBuilds({ amount, offset }); + } + + @AllowAnonymous() + @Get("average/time") + async getAverageBuildTimePerStatus(): Promise< + { + average_build_time: string; + status: string; + }[] + > { + return await this.builderService.getAverageBuildTimePerStatus(); } } diff --git a/backend/src/builder/builder.service.ts b/backend/src/builder/builder.service.ts index 00e9cce5..5d5ed646 100644 --- a/backend/src/builder/builder.service.ts +++ b/backend/src/builder/builder.service.ts @@ -241,6 +241,54 @@ export class BuilderService { .getRawMany(); } + async getStatusOfBuilds(options: { days: number }): Promise<{ status: string; count: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select("build.status") + .addSelect("COUNT(*) AS count") + .groupBy("build.status") + .orderBy("count", "DESC") + .cache(`status-of-builds-${options.days}`, 30000) + .getRawMany(); + } + + async getCountPerDay(options: { days: number; offset: number }): Promise<{ day: string; count: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select("DATE_TRUNC('day', build.timestamp) AS day") + .addSelect("COUNT(*) AS count") + .groupBy("day") + .orderBy("day", "DESC") + .cache(`count-per-day-${options.days}-${options.offset}`, 30000) + .take(options.days ?? 30) + .skip(options.offset ?? 0) + .getRawMany(); + } + + async downloadBuildsPerDay(options: { days: number; offset: number }): Promise<{ day: string; count: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select("DATE_TRUNC('day', build.timestamp) AS day") + .addSelect("COUNT(*) AS count") + .groupBy("day") + .orderBy("day", "DESC") + .cache(`build-counts-per-day-${options.days}`, 30000) + .take(options.days ?? 30) + .skip(options.offset ?? 0) + .getRawMany(); + } + + async getBuildsPerRepo(): Promise<{ repo: string; count: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select("repo.name AS repo") + .addSelect("COUNT(*) AS count") + .innerJoin("build.repo", "repo") + .groupBy("build.repo") + .cache(`builds-per-repo`, 30000) + .getRawMany(); + } + /** * Returns the number of builds per package. * @param options The amount to look back @@ -270,6 +318,47 @@ export class BuilderService { .getRawMany(); } } + + /** + * Returns the average build time per status. + * @returns The average build time per status + */ + async getAverageBuildTimePerStatus(): Promise<{ status: string; average_build_time: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select('AVG("timeToEnd") AS average_build_time') + .addSelect("status") + .where('"timeToEnd" IS NOT NULL') + .groupBy("status") + .orderBy("average_build_time", "DESC") + .cache(`average-build-time-per-status`, 30000) + .getRawMany(); + } + + /** + * Returns the latest builds. + * @param options The amount and offset + * @returns The latest builds with commit URL, commit hash, time to end, package name, and version + */ + async getLatestBuilds(options: { + amount: number; + offset: number; + }): Promise<{ logUrl: string; commit: string; timeToEnd: string; pkgname: string; version: string }[]> { + return await this.buildRepository + .createQueryBuilder("build") + .select('b."logUrl"') + .addSelect('b."commit"') + .addSelect('b."timeToEnd"') + .addSelect('p."pkgname"') + .addSelect('p."version"') + .from(Build, "b") + .innerJoin("b.pkgbase", "p") + .orderBy('p."lastUpdated"', "DESC") + .take(options.amount ?? 100) + .skip(options.offset ?? 0) + .cache(`latest-builds`, 30000) + .getRawMany(); + } } /** diff --git a/backend/src/repo-manager/repo-manager.service.ts b/backend/src/repo-manager/repo-manager.service.ts index dfc42d8d..be326295 100644 --- a/backend/src/repo-manager/repo-manager.service.ts +++ b/backend/src/repo-manager/repo-manager.service.ts @@ -624,7 +624,9 @@ class RepoManager { if (param.pkg.pkgname.endsWith("-bin")) continue; // We don't want to bump twice, either - const existingEntry: PackageBumpEntry = alreadyBumped.find((entry) => entry.pkg.pkgname === param.pkg.pkgname); + const existingEntry: PackageBumpEntry = alreadyBumped.find( + (entry) => entry.pkg.pkgname === param.pkg.pkgname, + ); if (existingEntry && typeof existingEntry.trigger !== "number" && "pkgname" in existingEntry.trigger) { Logger.warn( `Already bumped via ${existingEntry.triggerName}, skipping ${param.pkg.pkgname}`,