Skip to content

Commit bafbaab

Browse files
geroplroboquat
authored andcommitted
[server, installer] Make PrebuildRateLimiter period configurable
1 parent 2d4df42 commit bafbaab

File tree

21 files changed

+152
-63
lines changed

21 files changed

+152
-63
lines changed

components/server/ee/src/prebuilds/prebuild-manager.ts

+10-24
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import * as opentracing from "opentracing";
3434
import { StopWorkspacePolicy } from "@gitpod/ws-manager/lib";
3535
import { error } from "console";
3636
import { IncrementalPrebuildsService } from "./incremental-prebuilds-service";
37+
import { PrebuildRateLimiterConfig } from "../../../src/workspace/prebuild-rate-limiter";
3738

3839
export class WorkspaceRunningError extends Error {
3940
constructor(msg: string, public instance: WorkspaceInstance) {
@@ -49,9 +50,6 @@ export interface StartPrebuildParams {
4950
forcePrebuild?: boolean;
5051
}
5152

52-
const PREBUILD_LIMITER_WINDOW_SECONDS = 60;
53-
const PREBUILD_LIMITER_DEFAULT_LIMIT = 50;
54-
5553
@injectable()
5654
export class PrebuildManager {
5755
@inject(TracedWorkspaceDB) protected readonly workspaceDB: DBWithTracing<WorkspaceDB>;
@@ -389,36 +387,24 @@ export class PrebuildManager {
389387
}
390388

391389
private async shouldRateLimitPrebuild(span: opentracing.Span, cloneURL: string): Promise<boolean> {
392-
const windowStart = secondsBefore(new Date().toISOString(), PREBUILD_LIMITER_WINDOW_SECONDS);
390+
const rateLimit = PrebuildRateLimiterConfig.getConfigForCloneURL(this.config.prebuildLimiter, cloneURL);
391+
392+
const windowStart = secondsBefore(new Date().toISOString(), rateLimit.period);
393393
const unabortedCount = await this.workspaceDB
394394
.trace({ span })
395395
.countUnabortedPrebuildsSince(cloneURL, new Date(windowStart));
396-
const limit = this.getPrebuildRateLimitForCloneURL(cloneURL);
397396

398-
if (unabortedCount >= limit) {
399-
log.debug("Prebuild exceeds rate limit", { limit, unabortedPrebuildsCount: unabortedCount, cloneURL });
397+
if (unabortedCount >= rateLimit.limit) {
398+
log.debug("Prebuild exceeds rate limit", {
399+
...rateLimit,
400+
unabortedPrebuildsCount: unabortedCount,
401+
cloneURL,
402+
});
400403
return true;
401404
}
402405
return false;
403406
}
404407

405-
private getPrebuildRateLimitForCloneURL(cloneURL: string): number {
406-
// First we use any explicit overrides for a given cloneURL
407-
let limit = this.config.prebuildLimiter[cloneURL];
408-
if (limit > 0) {
409-
return limit;
410-
}
411-
412-
// Find if there is a default value set under the '*' key
413-
limit = this.config.prebuildLimiter["*"];
414-
if (limit > 0) {
415-
return limit;
416-
}
417-
418-
// Last resort default
419-
return PREBUILD_LIMITER_DEFAULT_LIMIT;
420-
}
421-
422408
private async shouldSkipInactiveProject(project: Project): Promise<boolean> {
423409
return await this.projectService.isProjectConsideredInactive(project.id);
424410
}

components/server/src/config.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import * as yaml from "js-yaml";
1717
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
1818
import { filePathTelepresenceAware } from "@gitpod/gitpod-protocol/lib/env";
1919
import { WorkspaceClasses, WorkspaceClassesConfig } from "./workspace/workspace-classes";
20+
import { PrebuildRateLimiters } from "./workspace/prebuild-rate-limiter";
2021

2122
export const Config = Symbol("Config");
2223
export type Config = Omit<
@@ -200,10 +201,10 @@ export interface ConfigSerialized {
200201
enablePayment?: boolean;
201202

202203
/**
203-
* Number of prebuilds that can be started in the last 1 minute.
204+
* Number of prebuilds that can be started in a given time period.
204205
* Key '*' specifies the default rate limit for a cloneURL, unless overriden by a specific cloneURL.
205206
*/
206-
prebuildLimiter: { [cloneURL: string]: number } & { "*": number };
207+
prebuildLimiter: PrebuildRateLimiters;
207208

208209
/**
209210
* If a numeric value interpreted as days is set, repositories not beeing opened with Gitpod are
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
export type PrebuildRateLimiters = { [cloneURL: string]: PrebuildRateLimiterConfig } & {
8+
"*": PrebuildRateLimiterConfig;
9+
};
10+
11+
export type PrebuildRateLimiterConfig = {
12+
// maximum number of requests per period
13+
limit: number;
14+
15+
// time period which the limit is enforce against in seconds
16+
period: number;
17+
};
18+
19+
export namespace PrebuildRateLimiterConfig {
20+
const DEFAULT_CONFIG: PrebuildRateLimiterConfig = {
21+
limit: 50,
22+
period: 50,
23+
};
24+
25+
export function getConfigForCloneURL(
26+
rateLimiters: PrebuildRateLimiters,
27+
cloneURL: string,
28+
): PrebuildRateLimiterConfig {
29+
// First we use any explicit overrides for a given cloneURL
30+
let config = rateLimiters[cloneURL];
31+
if (config) {
32+
return config;
33+
}
34+
35+
// Find if there is a default value set under the '*' key
36+
config = rateLimiters["*"];
37+
if (config) {
38+
return config;
39+
}
40+
41+
// Last resort default
42+
return DEFAULT_CONFIG;
43+
}
44+
}

install/installer/cmd/testdata/render/aws-setup/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/azure-setup/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/customization/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/external-registry/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/gcp-setup/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/http-proxy/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/insecure-s3-setup/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/kind-meta/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/kind-webapp/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/minimal/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/shortname/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install/installer/cmd/testdata/render/statefulset-customization/output.golden

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)