From 1770dc03e36603e6b159bbefa1ebb2242e297a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Thu, 2 Apr 2026 08:06:50 +0200 Subject: [PATCH] refactor: move timeout and busy logic to Runner --- src/Server.zig | 49 +++++++----------------------------------- src/browser/Runner.zig | 24 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/src/Server.zig b/src/Server.zig index 997aee46..16db3cc6 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -297,13 +297,12 @@ pub const Client = struct { } var cdp = &self.mode.cdp; - var last_message = milliTimestamp(.monotonic); - var ms_remaining = self.ws.timeout_ms; + const timeout_ms = self.ws.timeout_ms; while (true) { - const result = cdp.pageWait(ms_remaining) catch |wait_err| switch (wait_err) { + const result = cdp.pageWait(timeout_ms) catch |wait_err| switch (wait_err) { error.NoPage => { - const status = http.tick(ms_remaining) catch |err| { + const status = http.tick(timeout_ms) catch |err| { log.err(.app, "http tick", .{ .err = err }); return; }; @@ -314,10 +313,12 @@ pub const Client = struct { if (self.readSocket() == false) { return; } - last_message = milliTimestamp(.monotonic); - ms_remaining = self.ws.timeout_ms; continue; }, + error.Timeout => { + log.info(.app, "CDP timeout", .{}); + return; + }, else => return wait_err, }; @@ -326,46 +327,12 @@ pub const Client = struct { if (self.readSocket() == false) { return; } - last_message = milliTimestamp(.monotonic); - ms_remaining = self.ws.timeout_ms; - }, - .done => { - if (self.isBusy()) { - last_message = milliTimestamp(.monotonic); - ms_remaining = self.ws.timeout_ms; - continue; - } - const now = milliTimestamp(.monotonic); - const elapsed = now - last_message; - if (elapsed >= ms_remaining) { - log.info(.app, "CDP timeout", .{}); - return; - } - ms_remaining -= @intCast(elapsed); - last_message = now; }, + .done => unreachable, } } } - fn isBusy(self: *const Client) bool { - if (self.http.active > 0 or self.http.intercepted > 0) { - return true; - } - - const cdp = switch (self.mode) { - .cdp => |*c| c, - .http => return false, - }; - - const session = cdp.browser.session orelse return false; - if (session.browser.hasBackgroundTasks() or session.browser.msToNextMacrotask() != null) { - return true; - } - - return false; - } - fn blockingReadStart(ctx: *anyopaque) bool { const self: *Client = @ptrCast(@alignCast(ctx)); self.ws.setBlocking(true) catch |err| { diff --git a/src/browser/Runner.zig b/src/browser/Runner.zig index 8f56aacc..4a27aa7b 100644 --- a/src/browser/Runner.zig +++ b/src/browser/Runner.zig @@ -94,7 +94,18 @@ fn _wait(self: *Runner, comptime is_cdp: bool, opts: WaitOpts) !CDPWaitResult { const ms_elapsed = timer.lap() / 1_000_000; if (ms_elapsed >= ms_remaining) { - return .done; + // Don't timeout if there's still active work (HTTP requests, + // intercepted requests, background JS tasks, or pending macrotasks). + if (self.http_client.active > 0 or self.http_client.intercepted > 0) { + ms_remaining = opts.ms; + continue; + } + const browser = self.session.browser; + if (browser.hasBackgroundTasks() or browser.msToNextMacrotask() != null) { + ms_remaining = opts.ms; + continue; + } + return error.Timeout; } ms_remaining -= @intCast(ms_elapsed); if (next_ms > 0) { @@ -237,7 +248,16 @@ fn _tick(self: *Runner, comptime is_cdp: bool, opts: TickOpts) !CDPTickResult { page._parse_state = .{ .raw_done = @errorName(err) }; return err; }, - .raw_done => return .done, + .raw_done => { + if (comptime is_cdp) { + const http_result = try http_client.tick(@intCast(opts.ms)); + if (http_result == .cdp_socket) { + return .cdp_socket; + } + return .{ .ok = 0 }; + } + return .done; + }, } }