Skip to content

Commit

Permalink
Allow setOptions() to set runtime port (#610)
Browse files Browse the repository at this point in the history
* Allow `setOptions()` to set runtime port

* Automatically pick up existing port when updating

* Only update port, remove 'initial' parameter from update function and use helper function to parse port

* Update packages/miniflare/src/runtime/index.ts

Co-authored-by: MrBBot <[email protected]>

* Add test to ensure port is persisted between updates

---------

Co-authored-by: MrBBot <[email protected]>
  • Loading branch information
GregBrimble and mrbbot authored Jun 19, 2023
1 parent cfddac3 commit 5db7ae6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 6 deletions.
7 changes: 5 additions & 2 deletions packages/miniflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
Timers,
defaultTimers,
formatResponse,
maybeApply,
} from "./shared";
import { Storage } from "./storage";
import { CoreHeaders } from "./workers";
Expand Down Expand Up @@ -468,7 +469,7 @@ export class Miniflare {
this.#removeRuntimeExitHook = exitHook(() => void this.#runtime?.dispose());

// Update config and wait for runtime to start
await this.#assembleAndUpdateConfig(/* initial */ true);
await this.#assembleAndUpdateConfig();
}

async #handleLoopbackCustomService(
Expand Down Expand Up @@ -781,12 +782,14 @@ export class Miniflare {
return { services: Array.from(services.values()), sockets };
}

async #assembleAndUpdateConfig(initial = false) {
async #assembleAndUpdateConfig() {
const initial = !this.#runtimeEntryURL;
assert(this.#runtime !== undefined);
const config = await this.#assembleConfig();
const configBuffer = serializeConfig(config);
const maybePort = await this.#runtime.updateConfig(configBuffer, {
signal: this.#disposeController.signal,
entryPort: maybeApply(parseInt, this.#runtimeEntryURL?.port),
});
if (this.#disposeController.signal.aborted) return;
if (maybePort === undefined) {
Expand Down
14 changes: 10 additions & 4 deletions packages/miniflare/src/runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,15 @@ export interface RuntimeOptions {

export class Runtime {
readonly #command: string;
readonly #args: string[];

#process?: childProcess.ChildProcess;
#processExitPromise?: Promise<void>;

constructor(private opts: RuntimeOptions) {
this.#command = workerdPath;
}

get #args() {
const args: string[] = [
"serve",
// Required to use binary capnp config
Expand All @@ -98,18 +101,21 @@ export class Runtime {
args.push("--verbose");
}

this.#command = workerdPath;
this.#args = args;
return args;
}

async updateConfig(
configBuffer: Buffer,
options?: Abortable
options?: Abortable & Partial<Pick<RuntimeOptions, "entryPort">>
): Promise<number | undefined> {
// 1. Stop existing process (if any) and wait for exit
await this.dispose();
// TODO: what happens if runtime crashes?

if (options?.entryPort !== undefined) {
this.opts.entryPort = options.entryPort;
}

// 2. Start new process
const runtimeProcess = childProcess.spawn(this.#command, this.#args, {
stdio: ["pipe", "pipe", "pipe", "pipe"],
Expand Down
17 changes: 17 additions & 0 deletions packages/miniflare/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ test("Miniflare: validates options", async (t) => {
);
});

test("Miniflare: keeps port between updates", async (t) => {
const opts: MiniflareOptions = {
port: 0,
script: `addEventListener("fetch", (event) => {
event.respondWith(new Response("a"));
})`,
};
const mf = new Miniflare(opts);
const initialURL = await mf.ready;

await mf.setOptions(opts);
const updatedURL = await mf.ready;

t.not(initialURL.port, "0");
t.is(initialURL.port, updatedURL.port);
});

test("Miniflare: routes to multiple workers with fallback", async (t) => {
const opts: MiniflareOptions = {
workers: [
Expand Down

0 comments on commit 5db7ae6

Please sign in to comment.