ReviewOS

also looking at this

craft-native/craft

fix(ios): report async pool exhaustion as busy

#267
Merged glennmichael123 wants to merge codex/ios-busy-error-code into main
19 files +53 -65

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/zig/src/bridge_mobile_health.zigmodified+3-3
Changes to packages/zig/src/bridge_mobile_health.zig
@@ -178,7 +178,7 @@ pub const HealthBridge = struct {
178178 "requestHealthAuthorization: no free reply slot; {d} native calls are already awaiting one",
179179 .{ios_async.max_in_flight},
180180 );
181 return BridgeError.NativeCallFailed;
181 return BridgeError.Busy;
182182 };
183183 errdefer ios_async.abandon(ticket);
184184 const block = calls.claim(ticket, .{}) orelse {
@@ -240,7 +240,7 @@ pub const HealthBridge = struct {
240240 "saveHealthWorkout: no free reply slot; {d} native calls are already awaiting one",
241241 .{ios_async.max_in_flight},
242242 );
243 return BridgeError.NativeCallFailed;
243 return BridgeError.Busy;
244244 };
245245 errdefer ios_async.abandon(ticket);
246246
@@ -302,7 +302,7 @@ pub const HealthBridge = struct {
302302 "getHealthData: no free reply slot; {d} native calls are already awaiting one",
303303 .{ios_async.max_in_flight},
304304 );
305 return BridgeError.NativeCallFailed;
305 return BridgeError.Busy;
306306 };
307307 errdefer ios_async.abandon(ticket);
308308 const block = calls.claim(ticket, .{ .unit = unit }) orelse {
packages/zig/src/bridge_mobile_location.zigmodified+2-5
Changes to packages/zig/src/bridge_mobile_location.zig
@@ -1140,16 +1140,13 @@ fn nowMillis() f64 {
11401140 return @floatFromInt(compat.milliTimestamp());
11411141}
11421142
1143/// The answer for a full block pool, copied from `bridge_mobile_permissions`:
1144/// `BridgeError` has no "Busy", INVALID_PARAMETER is the migration notes'
1145/// designated stand-in, and the point is that the seventeenth concurrent call
1146/// gets an explicit rejection instead of a promise that never settles.
1143/// Reject a call when every asynchronous reply slot is already in use.
11471144fn poolFull() bridge_error.BridgeError {
11481145 std.log.warn(
11491146 "getCurrentPosition refused: all {d} async slots in flight",
11501147 .{ios_async.max_in_flight},
11511148 );
1152 return bridge_error.BridgeError.InvalidParameter;
1149 return bridge_error.BridgeError.Busy;
11531150}
11541151
11551152// =============================================================================
packages/zig/src/bridge_mobile_nfc.zigmodified+1-1
Changes to packages/zig/src/bridge_mobile_nfc.zig
@@ -156,7 +156,7 @@ const alert_message = "Hold your iPhone near the NFC tag";
156156
157157fn poolFull() BridgeError {
158158 std.log.warn("scanNFC refused: all {d} async slots in flight", .{ios_async.max_in_flight});
159 return BridgeError.InvalidParameter;
159 return BridgeError.Busy;
160160}
161161
162162// =============================================================================
packages/zig/src/bridge_mobile_notifications.zigmodified+2-5
Changes to packages/zig/src/bridge_mobile_notifications.zig
@@ -294,16 +294,13 @@ pub const NotificationsBridge = struct {
294294 }
295295};
296296
297/// The answer for a full block pool, copied from `bridge_mobile_permissions`:
298/// `BridgeError` has no "Busy", INVALID_PARAMETER is the migration notes'
299/// designated stand-in, and the point is that the seventeenth concurrent call
300/// gets an explicit rejection instead of a promise that never settles.
297/// Reject a call when every asynchronous reply slot is already in use.
301298fn poolFull() bridge_error.BridgeError {
302299 std.log.warn(
303300 "getPendingNotifications refused: all {d} async slots in flight",
304301 .{ios_async.max_in_flight},
305302 );
306 return bridge_error.BridgeError.InvalidParameter;
303 return bridge_error.BridgeError.Busy;
307304}
308305
309306// =============================================================================