add HttpClient.waitFor

This commit is contained in:
Muki Kiboigo
2026-05-25 12:02:46 -07:00
parent 9dc81f129c
commit ee4ae77a71
2 changed files with 46 additions and 35 deletions

View File

@@ -511,6 +511,12 @@ fn requestT(self: *Client, req: Request, owner: ?*Owner) !*Transfer {
return transfer;
}
pub fn waitFor(self: *Client, ctx: anytype, comptime isDone: fn (@TypeOf(ctx)) bool) !void {
while (!isDone(ctx)) {
try self.tick(200, .sync_wait);
}
}
const SyncContext = struct {
allocator: Allocator,
completion: union(enum) {
@@ -574,17 +580,22 @@ pub fn syncRequest(self: *Client, allocator: Allocator, req: Request) !SyncRespo
r.shutdown_callback = SyncContext.shutdownCallback;
const transfer = try self.requestT(r, null);
while (sync_ctx.completion == .in_progress) {
self.tick(200, .sync_wait) catch |err| {
if (sync_ctx.completion == .in_progress) {
// tick failed for a reason unrelated to our transfer (likely OOM or
// client disconnect). transfer.req.ctx points at &sync_ctx on this
// stack — abort to sever that reference before we return
transfer.abort(err);
self.waitFor(
&sync_ctx,
struct {
fn done(ctx: *SyncContext) bool {
return ctx.completion != .in_progress;
}
return err;
};
}
}.done,
) catch |err| {
if (sync_ctx.completion == .in_progress) {
// tick failed for a reason unrelated to our transfer (likely OOM or
// client disconnect). transfer.req.ctx points at &sync_ctx on this
// stack — abort to sever that reference before we return
transfer.abort(err);
}
return err;
};
switch (sync_ctx.completion) {
.in_progress => @panic("Impossible to be in progress here."),

View File

@@ -296,32 +296,32 @@ pub fn waitForImport(self: *ScriptManagerBase, url: [:0]const u8) !ModuleSource
self.is_evaluating = true;
defer self.is_evaluating = was_evaluating;
var client = self.client;
while (true) {
switch (entry.value_ptr.state) {
.loading => {
_ = try client.tick(200, .sync_wait);
continue;
},
.done => |script| {
var shared = false;
const buffer = entry.value_ptr.buffer;
const waiters = entry.value_ptr.waiters;
if (waiters == 1) {
self.imported_modules.removeByPtr(entry.key_ptr);
} else {
shared = true;
entry.value_ptr.waiters = waiters - 1;
}
return .{
.buffer = buffer,
.shared = shared,
.script = script,
};
},
.err => return error.Failed,
try self.client.waitFor(entry.value_ptr, struct {
fn done(m: *ImportedModule) bool {
return m.state != .loading;
}
}.done);
switch (entry.value_ptr.state) {
.loading => @panic("Impossible to be loading here."),
.done => |script| {
var shared = false;
const buffer = entry.value_ptr.buffer;
const waiters = entry.value_ptr.waiters;
if (waiters == 1) {
self.imported_modules.removeByPtr(entry.key_ptr);
} else {
shared = true;
entry.value_ptr.waiters = waiters - 1;
}
return .{
.buffer = buffer,
.shared = shared,
.script = script,
};
},
.err => return error.Failed,
}
}