Skip to content

Commit

Permalink
Support user CPU time limit
Browse files Browse the repository at this point in the history
User limits provided via script metadata on upload

Example configuration:
```
[limits]
cpu_ms = 20000
```
  • Loading branch information
matthewdavidrodgers committed Oct 18, 2023
1 parent 0760356 commit 2ea0049
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .changeset/pink-jokes-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"wrangler": minor
---

Support user limits for CPU time

User limits provided via script metadata on upload

Example configuration:

```
[limits]
cpu_ms = 20000
```
28 changes: 28 additions & 0 deletions packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5072,6 +5072,29 @@ addEventListener('fetch', event => {});`
});
});

describe("user limits", () => {
it("should allow specifying a cpu millisecond limit", async () => {
writeWranglerToml({
limits: { cpu_ms: 15_000 },
});

await fs.promises.writeFile("index.js", `export default {};`);
mockSubDomainRequest();
mockUploadWorkerRequest({
expectedLimits: { cpu_ms: 15_000 },
});

await runWrangler("publish index.js");
expect(std.out).toMatchInlineSnapshot(`
"Total Upload: xx KiB / gzip: xx KiB
Uploaded test-name (TIMINGS)
Published test-name (TIMINGS)
https://test-name.test-sub-domain.workers.dev
Current Deployment ID: Galaxy-Class"
`);
});
});

describe("bindings", () => {
it("should allow bindings with different names", async () => {
writeWranglerToml({
Expand Down Expand Up @@ -8637,6 +8660,7 @@ export function mockUploadWorkerRequest(
expectedTailConsumers?: CfWorkerInit["tail_consumers"];
expectedUnsafeMetaData?: Record<string, string>;
expectedCapnpSchema?: string;
expectedLimits?: CfWorkerInit["limits"];
env?: string;
legacyEnv?: boolean;
keepVars?: boolean;
Expand All @@ -8658,6 +8682,7 @@ export function mockUploadWorkerRequest(
expectedTailConsumers,
expectedUnsafeMetaData,
expectedCapnpSchema,
expectedLimits,
keepVars,
} = options;
if (env && !legacyEnv) {
Expand Down Expand Up @@ -8734,6 +8759,9 @@ export function mockUploadWorkerRequest(
expectedCapnpSchema
);
}
if ("expectedLimits" in options) {
expect(metadata.limits).toEqual(expectedLimits);
}
if (expectedUnsafeMetaData !== undefined) {
Object.keys(expectedUnsafeMetaData).forEach((key) => {
expect(metadata[key]).toEqual(expectedUnsafeMetaData[key]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function createWorkerBundleFormData(workerBundle: BundleResult): FormData {
logpush: undefined,
placement: undefined,
tail_consumers: undefined,
limits: undefined,
};

return createWorkerUploadForm(worker);
Expand Down
13 changes: 13 additions & 0 deletions packages/wrangler/src/config/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ interface EnvironmentInheritable {
*/
usage_model: "bundled" | "unbound" | undefined;

/**
* Specify limits for runtime behavior.
* Only supported for the "standard" Usage Model
*
* @inheritable
*/
limits: UserLimits | undefined;

/**
* An ordered list of rules that define which modules to import,
* and what type to import them as. You will need to specify rules
Expand Down Expand Up @@ -736,3 +744,8 @@ export interface DispatchNamespaceOutbound {
/** (Optional) List of parameter names, for sending context from your dispatch worker to the outbound handler */
parameters?: string[];
}

export interface UserLimits {
/** Maximum allowed CPU time for a worker's invocation in milliseconds */
cpu_ms: number;
}
26 changes: 26 additions & 0 deletions packages/wrangler/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,7 @@ function normalizeAndValidateEnvironment(
isOneOf("bundled", "unbound"),
undefined
),
limits: normalizeAndValidateLimits(diagnostics, topLevelEnv, rawEnv),
placement: normalizeAndValidatePlacement(diagnostics, topLevelEnv, rawEnv),
build,
workers_dev,
Expand Down Expand Up @@ -2801,3 +2802,28 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {

return isValid;
};

function normalizeAndValidateLimits(
diagnostics: Diagnostics,
topLevelEnv: Environment | undefined,
rawEnv: RawEnvironment
): Config["limits"] {
if (rawEnv.limits) {
validateRequiredProperty(
diagnostics,
"limits",
"cpu_ms",
rawEnv.limits.cpu_ms,
"number"
);
}

return inheritable(
diagnostics,
topLevelEnv,
rawEnv,
"limits",
() => true,
undefined
);
}
1 change: 1 addition & 0 deletions packages/wrangler/src/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
logpush: props.logpush !== undefined ? props.logpush : config.logpush,
placement,
tail_consumers: config.tail_consumers,
limits: config.limits,
};

// As this is not deterministic for testing, we detect if in a jest environment and run asynchronously
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
CfDurableObjectMigrations,
CfPlacement,
CfTailConsumer,
CfUserLimits,
} from "./worker.js";
import type { Json } from "miniflare";

Expand Down Expand Up @@ -105,6 +106,7 @@ export interface WorkerMetadata {
logpush?: boolean;
placement?: CfPlacement;
tail_consumers?: CfTailConsumer[];
limits?: CfUserLimits;
// Allow unsafe.metadata to add arbitrary properties at runtime
[key: string]: unknown;
}
Expand All @@ -125,6 +127,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
logpush,
placement,
tail_consumers,
limits,
} = worker;

let { modules } = worker;
Expand Down Expand Up @@ -462,6 +465,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
...(logpush !== undefined && { logpush }),
...(placement && { placement }),
...(tail_consumers && { tail_consumers }),
...(limits && { limits }),
};

if (bindings.unsafe?.metadata !== undefined) {
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/deployment-bundle/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ export interface CfTailConsumer {
environment?: string;
}

export interface CfUserLimits {
cpu_ms?: number;
}

/**
* Options for creating a `CfWorker`.
*/
Expand Down Expand Up @@ -298,6 +302,7 @@ export interface CfWorkerInit {
logpush: boolean | undefined;
placement: CfPlacement | undefined;
tail_consumers: CfTailConsumer[] | undefined;
limits: CfUserLimits | undefined;
}

export interface CfWorkerContext {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/dev/remote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ async function createRemoteWorkerInit(props: {
logpush: false,
placement: undefined, // no placement in dev
tail_consumers: undefined, // no tail consumers in dev - TODO revisit?
limits: undefined, // no limits in preview - not supported yet but can be added
};

return init;
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/secret/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ async function createDraftWorker({
logpush: false,
placement: undefined,
tail_consumers: undefined,
limits: undefined,
}),
}
);
Expand Down

0 comments on commit 2ea0049

Please sign in to comment.