Skip to content

Commit 764ec1e

Browse files
[wrangler] make sure that the ready-on message is printed after the appropriate runtime controller is ready
1 parent e50d5f7 commit 764ec1e

File tree

7 files changed

+91
-27
lines changed

7 files changed

+91
-27
lines changed

.changeset/fluffy-seals-arrive.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
make sure that the ready-on message is printed after the appropriate runtime controller is ready
6+
7+
fix the fact that when starting a local (or remote) dev session the log saying `Ready on http://localhost:xxxx` could be displayed before the runtime is actually ready to handle requests (this is quite noticeable when locally running dev sessions with containers, where the ready message currently gets displayed before the container images building/pulling process)

fixtures/interactive-dev-tests/tests/index.test.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -500,11 +500,10 @@ baseDescribe.skipIf(process.platform !== "linux" && process.env.CI === "true")(
500500
});
501501

502502
it("should allow quitting while the image is building", async () => {
503-
const wrangler = await startWranglerDev([
504-
"dev",
505-
"-c",
506-
path.join(tmpDir, "wrangler.jsonc"),
507-
]);
503+
const wrangler = await startWranglerDev(
504+
["dev", "-c", path.join(tmpDir, "wrangler.jsonc")],
505+
true
506+
);
508507

509508
const waitForOptions = {
510509
timeout: 10_000,
@@ -524,11 +523,10 @@ baseDescribe.skipIf(process.platform !== "linux" && process.env.CI === "true")(
524523
});
525524

526525
it("should rebuilding while the image is building", async () => {
527-
const wrangler = await startWranglerDev([
528-
"dev",
529-
"-c",
530-
path.join(tmpDir, "wrangler.jsonc"),
531-
]);
526+
const wrangler = await startWranglerDev(
527+
["dev", "-c", path.join(tmpDir, "wrangler.jsonc")],
528+
true
529+
);
532530

533531
const waitForOptions = {
534532
timeout: 15_000,

fixtures/pages-workerjs-app/tests/index.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { rename } from "node:fs/promises";
33
import path, { resolve } from "node:path";
44
import { setTimeout } from "node:timers/promises";
55
import { fetch } from "undici";
6-
import { describe, it } from "vitest";
6+
import { describe, it, vi } from "vitest";
77
import { runWranglerPagesDev } from "../../shared/src/run-wrangler-long-lived";
88

99
describe("Pages _worker.js", () => {
@@ -72,6 +72,15 @@ describe("Pages _worker.js", () => {
7272
"--port=0",
7373
"--inspector-port=0",
7474
]);
75+
vi.waitFor(
76+
() => {
77+
expect(getOutput()).toContain("Ready on");
78+
},
79+
{
80+
timeout: 5_000,
81+
}
82+
);
83+
await setTimeout(200);
7584
try {
7685
clearOutput();
7786
await tryRename(
@@ -109,6 +118,15 @@ describe("Pages _worker.js", () => {
109118
"--port=0",
110119
"--inspector-port=0",
111120
]);
121+
vi.waitFor(
122+
() => {
123+
expect(getOutput()).toContain("Ready on");
124+
},
125+
{
126+
timeout: 5_000,
127+
}
128+
);
129+
await setTimeout(200);
112130
try {
113131
clearOutput();
114132
await tryRename(

packages/wrangler/e2e/containers.dev.test.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,15 @@ for (const source of imageSource) {
196196
it(`will be able to interact with the container`, async () => {
197197
const worker = helper.runLongLived("wrangler dev");
198198
const ready = await worker.waitForReady();
199-
await worker.readUntil(/Container image\(s\) ready/);
200199

201-
let response = await fetch(`${ready.url}/status`);
202-
expect(response.status).toBe(200);
203-
let status = await response.json();
204-
expect(status).toBe(false);
200+
await vi.waitFor(async () => {
201+
const response = await fetch(`${ready.url}/status`);
202+
expect(response.status).toBe(200);
203+
const status = await response.json();
204+
expect(status).toBe(false);
205+
});
205206

206-
response = await fetch(`${ready.url}/start`);
207+
let response = await fetch(`${ready.url}/start`);
207208
let text = await response.text();
208209
expect(response.status).toBe(200);
209210
expect(text).toBe("Container create request sent...");
@@ -212,7 +213,7 @@ for (const source of imageSource) {
212213
await new Promise((resolve) => setTimeout(resolve, 2_000));
213214

214215
response = await fetch(`${ready.url}/status`);
215-
status = await response.json();
216+
const status = await response.json();
216217
expect(response.status).toBe(200);
217218
expect(status).toBe(true);
218219

@@ -254,6 +255,24 @@ for (const source of imageSource) {
254255
);
255256
});
256257

258+
it("will display the ready-on message after the container(s) have been built/pulled", async () => {
259+
const worker = helper.runLongLived("wrangler dev");
260+
const readyRegexp = /Ready on (http:\/\/[a-z0-9.]+:[0-9]+)/;
261+
await worker.readUntil(readyRegexp);
262+
263+
await worker.stop();
264+
265+
const fullOutput = await worker.output;
266+
const indexOfContainersReadyMessage = fullOutput.indexOf(
267+
"Container image(s) ready"
268+
);
269+
270+
const indexOfReadyOnMessage = fullOutput.indexOf("Ready on");
271+
expect(indexOfReadyOnMessage).toBeGreaterThan(
272+
indexOfContainersReadyMessage
273+
);
274+
});
275+
257276
it("won't start the container service if --enable-containers is set to false via CLI", async () => {
258277
const worker = helper.runLongLived(
259278
"wrangler dev --enable-containers=false"

packages/wrangler/e2e/helpers/wrangler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class WranglerLongLivedCommand extends LongLivedCommand {
3535
super(getWranglerCommand(wranglerCommand), getOptions(options));
3636
}
3737

38-
async waitForReady(readTimeout = 5_000): Promise<{ url: string }> {
38+
async waitForReady(readTimeout = 15_000): Promise<{ url: string }> {
3939
const match = await this.readUntil(
4040
/Ready on (?<url>https?:\/\/.*)/,
4141
readTimeout

packages/wrangler/e2e/remote-binding/dev-remote-bindings.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,18 @@ describe.skipIf(!CLOUDFLARE_ACCOUNT_ID)(
177177
Your Worker has access to the following bindings:
178178
Binding Resource Mode
179179
env.AI AI remote
180-
[wrangler:info] Ready on http://<HOST>:<PORT>
181180
▲ [WARNING] AI bindings always access remote resources, and so may incur usage charges even in local dev. To suppress this warning, set \`experimental_remote: true\` for the binding definition in your configuration file.
182181
⎔ Starting local server...
182+
[wrangler:info] Ready on http://<HOST>:<PORT>
183183
[wrangler:info] GET / 200 OK (TIMINGS)`;
184184

185185
const output2 = dedent`
186186
Your Worker has access to the following bindings:
187187
Binding Resource Mode
188188
env.AI AI remote
189189
▲ [WARNING] AI bindings always access remote resources, and so may incur usage charges even in local dev. To suppress this warning, set \`experimental_remote: true\` for the binding definition in your configuration file.
190-
[wrangler:info] Ready on http://<HOST>:<PORT>
191190
⎔ Starting local server...
191+
[wrangler:info] Ready on http://<HOST>:<PORT>
192192
[wrangler:info] GET / 200 OK (TIMINGS)`;
193193

194194
const normalizedOutput = normalizeOutput(worker.currentOutput);

packages/wrangler/src/api/startDevWorker/ProxyController.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import type {
4141
} from "./events";
4242
import type { StartDevWorkerOptions } from "./types";
4343
import type { DeferredPromise } from "./utils";
44-
import type { MiniflareOptions } from "miniflare";
44+
import type { LogOptions, MiniflareOptions } from "miniflare";
4545

4646
type ProxyControllerEventMap = ControllerEventMap & {
4747
ready: [ReadyEvent];
@@ -50,6 +50,8 @@ type ProxyControllerEventMap = ControllerEventMap & {
5050
export class ProxyController extends Controller<ProxyControllerEventMap> {
5151
public ready = createDeferred<ReadyEvent>();
5252

53+
public localServerReady = createDeferred<void>();
54+
5355
public proxyWorker?: Miniflare;
5456
proxyWorkerOptions?: MiniflareOptions;
5557
private inspectorProxyWorkerWebSocket?: DeferredPromise<WebSocket>;
@@ -126,11 +128,17 @@ export class ProxyController extends Controller<ProxyControllerEventMap> {
126128
verbose: logger.loggerLevel === "debug",
127129

128130
// log requests into the ProxyWorker (for local + remote mode)
129-
log: new ProxyControllerLogger(castLogLevel(logger.loggerLevel), {
130-
prefix:
131-
// if debugging, log requests with specic ProxyWorker prefix
132-
logger.loggerLevel === "debug" ? "wrangler-ProxyWorker" : "wrangler",
133-
}),
131+
log: new ProxyControllerLogger(
132+
castLogLevel(logger.loggerLevel),
133+
{
134+
prefix:
135+
// if debugging, log requests with specic ProxyWorker prefix
136+
logger.loggerLevel === "debug"
137+
? "wrangler-ProxyWorker"
138+
: "wrangler",
139+
},
140+
this.localServerReady.promise
141+
),
134142
handleRuntimeStdio,
135143
liveReload: false,
136144
};
@@ -419,6 +427,8 @@ export class ProxyController extends Controller<ProxyControllerEventMap> {
419427
}
420428
}
421429
onReloadComplete(data: ReloadCompleteEvent) {
430+
this.localServerReady.resolve();
431+
422432
this.latestConfig = data.config;
423433
this.latestBundle = data.bundle;
424434

@@ -606,6 +616,18 @@ export class ProxyController extends Controller<ProxyControllerEventMap> {
606616
}
607617

608618
class ProxyControllerLogger extends WranglerLog {
619+
constructor(
620+
level: LogLevel,
621+
opts: LogOptions,
622+
private localServerReady: Promise<void>
623+
) {
624+
super(level, opts);
625+
}
626+
627+
logReady(message: string): void {
628+
this.localServerReady.then(() => super.logReady(message)).catch(() => {});
629+
}
630+
609631
log(message: string) {
610632
// filter out request logs being handled by the ProxyWorker
611633
// the requests log remaining are handled by the UserWorker

0 commit comments

Comments
 (0)