From f3a1920d8fd2da7405e7c6fe549cf8c7ce3eb5e2 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Tue, 6 Feb 2024 15:42:13 +0100 Subject: [PATCH] async: yield between fetch steps in test cli --- src/async/test.zig | 51 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/async/test.zig b/src/async/test.zig index 763e43d8..56bfc09c 100644 --- a/src/async/test.zig +++ b/src/async/test.zig @@ -5,8 +5,6 @@ const Request = @import("Client.zig").Request; pub const Loop = @import("jsruntime").Loop; -const TCPClient = @import("tcp.zig").Client; - const url = "https://w3.org"; test "blocking mode fetch API" { @@ -67,39 +65,65 @@ const AsyncClient = struct { const YieldImpl = Loop.Yield(AsyncRequest); const AsyncRequest = struct { + const State = enum { new, open, send, finish, wait, done }; + cli: *Client, uri: std.Uri, headers: std.http.Headers, + req: ?Request = undefined, + state: State = .new, + impl: YieldImpl, - done: bool = false, err: ?anyerror = null, pub fn deinit(self: *AsyncRequest) void { + if (self.req) |*r| r.deinit(); self.headers.deinit(); } pub fn fetch(self: *AsyncRequest) void { + self.state = .new; return self.impl.yield(self); } fn onerr(self: *AsyncRequest, err: anyerror) void { + self.state = .done; self.err = err; } pub fn onYield(self: *AsyncRequest, err: ?anyerror) void { - defer self.done = true; if (err) |e| return self.onerr(e); - var req = self.cli.open(.GET, self.uri, self.headers, .{}) catch |e| return self.onerr(e); - defer req.deinit(); - req.send(.{}) catch |e| return self.onerr(e); - req.finish() catch |e| return self.onerr(e); - req.wait() catch |e| return self.onerr(e); + switch (self.state) { + .new => { + self.state = .open; + self.req = self.cli.open(.GET, self.uri, self.headers, .{}) catch |e| return self.onerr(e); + }, + .open => { + self.state = .send; + self.req.?.send(.{}) catch |e| return self.onerr(e); + }, + .send => { + self.state = .finish; + self.req.?.finish() catch |e| return self.onerr(e); + }, + .finish => { + self.state = .wait; + self.req.?.wait() catch |e| return self.onerr(e); + }, + .wait => { + self.state = .done; + return; + }, + .done => return, + } + + return self.impl.yield(self); } pub fn wait(self: *AsyncRequest) !void { - while (!self.done) try self.impl.tick(); + while (self.state != .done) try self.impl.tick(); if (self.err) |err| return err; } }; @@ -117,7 +141,7 @@ const AsyncClient = struct { self.cli.deinit(); } - pub fn create(self: *AsyncClient, uri: std.Uri) !AsyncRequest { + pub fn createRequest(self: *AsyncClient, uri: std.Uri) !AsyncRequest { return .{ .impl = YieldImpl.init(self.cli.loop), .cli = &self.cli, @@ -136,12 +160,11 @@ test "non blocking client" { var client = AsyncClient.init(alloc, &loop); defer client.deinit(); - var reqs: [10]AsyncClient.AsyncRequest = undefined; + var reqs: [3]AsyncClient.AsyncRequest = undefined; for (0..reqs.len) |i| { - reqs[i] = try client.create(try std.Uri.parse(url)); + reqs[i] = try client.createRequest(try std.Uri.parse(url)); reqs[i].fetch(); } - for (0..reqs.len) |i| { try reqs[i].wait(); reqs[i].deinit();