From cd5e5ece40cf3f6c18bd1094ae48d74a283960d7 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Mon, 18 May 2026 07:35:50 -0700 Subject: [PATCH] serve from cache on next client tick --- src/network/layer/CacheLayer.zig | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/network/layer/CacheLayer.zig b/src/network/layer/CacheLayer.zig index 5990a326..f08b0f6a 100644 --- a/src/network/layer/CacheLayer.zig +++ b/src/network/layer/CacheLayer.zig @@ -21,6 +21,7 @@ const lp = @import("lightpanda"); const Layer = @import("../../browser/HttpClient.zig").Layer; const Client = @import("../../browser/HttpClient.zig").Client; +const NextTickNode = @import("../../browser/HttpClient.zig").NextTickNode; const Request = @import("../../browser/HttpClient.zig").Request; const Transfer = @import("../../browser/HttpClient.zig").Transfer; const Response = @import("../../browser/HttpClient.zig").Response; @@ -72,11 +73,30 @@ fn request(ptr: *anyopaque, transfer: *Transfer) anyerror!void { &.{ .transfer = transfer }, ); - // Cache hit: serve synchronously from the original callbacks, then - // tear down. On error, the transfer is still alive and Client.request's - // errdefer will handle cleanup (state stays .created). - try serveFromCache(req, &cached); - transfer.deinit(); + const CacheServeCtx = struct { + transfer: *Transfer, + cached: CachedResponse, + }; + + const ctx = try arena.create(CacheServeCtx); + ctx.* = .{ .transfer = transfer, .cached = cached }; + + const next_tick = try arena.create(NextTickNode); + next_tick.* = .{ + .ctx = ctx, + .run = struct { + fn run(ctx_ptr: *anyopaque) anyerror!void { + const c: *CacheServeCtx = @ptrCast(@alignCast(ctx_ptr)); + serveFromCache(&c.transfer.req, &c.cached) catch |err| { + c.transfer.req.error_callback(c.transfer.req.ctx, err); + }; + c.transfer.deinit(); + } + }.run, + }; + + transfer.loop_owned = true; + transfer.client.runNextTick(next_tick); return; }