Skip to content

Commit

Permalink
[wrangler] feat: add support for placement in wrangler config (#3095)
Browse files Browse the repository at this point in the history
* [wrangler] feat: add support for placement in wrangler config

Allows a placement object in the wrangler config with a mode of off or
smart to configure Smart placement.

* increase specificity for workers placement

* Add example to placement changeset
  • Loading branch information
zebp committed May 8, 2023
1 parent a97344d commit 133c042
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 1 deletion.
12 changes: 12 additions & 0 deletions .changeset/short-bottles-smell.md
@@ -0,0 +1,12 @@
---
"wrangler": minor
---

feat: add support for placement in wrangler config

Allows a `placement` object in the wrangler config with a mode of `off` or `smart` to configure [Smart placement](https://developers.cloudflare.com/workers/platform/smart-placement/). Enabling Smart Placement can be done in your `wrangler.toml` like:

```toml
[placement]
mode = "smart"
```
8 changes: 8 additions & 0 deletions packages/wrangler/src/__tests__/configuration.test.ts
Expand Up @@ -84,6 +84,7 @@ describe("normalizeAndValidateConfig()", () => {
first_party_worker: undefined,
keep_vars: undefined,
logpush: undefined,
placement: undefined,
});
expect(diagnostics.hasErrors()).toBe(false);
expect(diagnostics.hasWarnings()).toBe(false);
Expand Down Expand Up @@ -955,6 +956,9 @@ describe("normalizeAndValidateConfig()", () => {
node_compat: true,
first_party_worker: true,
logpush: true,
placement: {
mode: "smart",
},
};

const { config, diagnostics } = normalizeAndValidateConfig(
Expand Down Expand Up @@ -1030,6 +1034,9 @@ describe("normalizeAndValidateConfig()", () => {
node_compat: "INVALID",
first_party_worker: "INVALID",
logpush: "INVALID",
placement: {
mode: "INVALID",
},
} as unknown as RawEnvironment;

const { config, diagnostics } = normalizeAndValidateConfig(
Expand Down Expand Up @@ -1093,6 +1100,7 @@ describe("normalizeAndValidateConfig()", () => {
- Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
- Expected \\"main\\" to be of type string but got 1333.
- Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
- Expected \\"placement.mode\\" field to be one of [\\"off\\",\\"smart\\"] but got \\"INVALID\\".
- The field \\"define.DEF1\\" should be a string but got 1777.
- Expected \\"no_bundle\\" to be of type boolean but got \\"INVALID\\".
- Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
Expand Down
Expand Up @@ -70,6 +70,7 @@ function createWorkerBundleFormData(workerBundle: BundleResult): FormData {
usage_model: undefined,
keepVars: undefined,
logpush: undefined,
placement: undefined,
};

return createWorkerUploadForm(worker);
Expand Down
7 changes: 7 additions & 0 deletions packages/wrangler/src/config/environment.ts
Expand Up @@ -265,6 +265,13 @@ interface EnvironmentInheritable {
* @inheritable
*/
logpush: boolean | undefined;

/**
* Specify how the worker should be located to minimize round-trip time.
*
* More details: https://developers.cloudflare.com/workers/platform/smart-placement/
*/
placement: { mode: "off" | "smart" } | undefined;
}

export type DurableObjectBindings = {
Expand Down
27 changes: 27 additions & 0 deletions packages/wrangler/src/config/validation.ts
Expand Up @@ -873,6 +873,32 @@ function validateRoutes(
);
}

function normalizeAndValidatePlacement(
diagnostics: Diagnostics,
topLevelEnv: Environment | undefined,
rawEnv: RawEnvironment
): Config["placement"] {
if (rawEnv.placement) {
validateRequiredProperty(
diagnostics,
"placement",
"mode",
rawEnv.placement.mode,
"string",
["off", "smart"]
);
}

return inheritable(
diagnostics,
topLevelEnv,
rawEnv,
"placement",
() => true,
undefined
);
}

/**
* Validate top-level environment configuration and return the normalized values.
*/
Expand Down Expand Up @@ -1060,6 +1086,7 @@ function normalizeAndValidateEnvironment(
isOneOf("bundled", "unbound"),
undefined
),
placement: normalizeAndValidatePlacement(diagnostics, topLevelEnv, rawEnv),
build,
workers_dev,
// Not inherited fields
Expand Down
4 changes: 4 additions & 0 deletions packages/wrangler/src/create-worker-upload-form.ts
Expand Up @@ -4,6 +4,7 @@ import type {
CfWorkerInit,
CfModuleType,
CfDurableObjectMigrations,
CfPlacement,
} from "./worker.js";

export function toMimeType(type: CfModuleType): string {
Expand Down Expand Up @@ -71,6 +72,7 @@ export interface WorkerMetadata {
bindings: WorkerMetadataBinding[];
keep_bindings?: WorkerMetadataBinding["type"][];
logpush?: boolean;
placement?: CfPlacement;
// Allow unsafe.metadata to add arbitary properties at runtime
[key: string]: unknown;
}
Expand All @@ -89,6 +91,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
compatibility_flags,
keepVars,
logpush,
placement,
} = worker;

let { modules } = worker;
Expand Down Expand Up @@ -320,6 +323,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
capnp_schema: bindings.logfwdr?.schema,
...(keepVars && { keep_bindings: ["plain_text", "json"] }),
...(logpush !== undefined && { logpush }),
...(placement && { placement }),
};

if (bindings.unsafe?.metadata !== undefined) {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/dev/remote.tsx
Expand Up @@ -576,6 +576,7 @@ async function createRemoteWorkerInit(props: {
usage_model: props.usageModel,
keepVars: true,
logpush: false,
placement: undefined, // no placement in dev
};

return init;
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/init.ts
Expand Up @@ -80,6 +80,7 @@ export type ServiceMetadataRes = {
usage_model: "bundled" | "unbound";
compatibility_date: string;
last_deployed_from?: "wrangler" | "dash" | "api";
placement_mode?: "smart";
};
};
created_on: string;
Expand Down Expand Up @@ -868,6 +869,10 @@ async function getWorkerConfig(
new Date().toISOString().substring(0, 10),
...routeOrRoutesToConfig,
usage_model: serviceEnvMetadata.script.usage_model,
placement:
serviceEnvMetadata.script.placement_mode === "smart"
? { mode: "smart" }
: undefined,
...(durableObjectClassNames.length
? {
migrations: [
Expand Down
7 changes: 6 additions & 1 deletion packages/wrangler/src/publish/publish.ts
Expand Up @@ -35,7 +35,7 @@ import type {
import type { Entry } from "../entry";
import type { PutConsumerBody } from "../queues/client";
import type { AssetPaths } from "../sites";
import type { CfWorkerInit } from "../worker";
import type { CfWorkerInit, CfPlacement } from "../worker";

type Props = {
config: Config;
Expand Down Expand Up @@ -571,6 +571,10 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
});
}

// The upload API only accepts an empty string or no specified placement for the "off" mode.
const placement: CfPlacement | undefined =
config.placement?.mode === "smart" ? { mode: "smart" } : undefined;

const worker: CfWorkerInit = {
name: scriptName,
main: {
Expand All @@ -586,6 +590,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
usage_model: config.usage_model,
keepVars,
logpush: props.logpush !== undefined ? props.logpush : config.logpush,
placement,
};

// As this is not deterministic for testing, we detect if in a jest environment and run asynchronously
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/secret/index.ts
Expand Up @@ -123,6 +123,7 @@ export const secret = (secretYargs: CommonYargsArgv) => {
usage_model: undefined,
keepVars: false, // this doesn't matter since it's a new script anyway
logpush: false,
placement: undefined,
}),
}
);
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/worker.ts
Expand Up @@ -203,6 +203,10 @@ export interface CfDurableObjectMigrations {
}[];
}

export interface CfPlacement {
mode: "smart";
}

/**
* Options for creating a `CfWorker`.
*/
Expand Down Expand Up @@ -246,6 +250,7 @@ export interface CfWorkerInit {
usage_model: "bundled" | "unbound" | undefined;
keepVars: boolean | undefined;
logpush: boolean | undefined;
placement: CfPlacement | undefined;
}

export interface CfWorkerContext {
Expand Down

0 comments on commit 133c042

Please sign in to comment.