GET /xrpc/app.bsky.actor.searchActorsTypeahead typeahead.waow.tech
16
fork

Configure Feed

Select the types of activity you want to include in your feed.

replace manual JSON construction with std.json.Stringify

writeJsonEscaped + ~45 lines of hand-rolled brace/comma/quote
juggling → jw.write(...) with emit_null_optional_fields = false.
stdlib handles all escaping per RFC 8259.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+19 -63
+19 -63
ingester/src/main.zig
··· 224 224 } 225 225 }; 226 226 227 - fn writeJsonEscaped(w: anytype, s: []const u8) !void { 228 - for (s) |c| { 229 - switch (c) { 230 - '"' => try w.writeAll("\\\""), 231 - '\\' => try w.writeAll("\\\\"), 232 - '\n' => try w.writeAll("\\n"), 233 - '\r' => try w.writeAll("\\r"), 234 - '\t' => try w.writeAll("\\t"), 235 - else => { 236 - if (c < 0x20) { 237 - try w.print("\\u{x:0>4}", .{c}); 238 - } else { 239 - try w.writeByte(c); 240 - } 241 - }, 242 - } 243 - } 244 - } 245 - 246 227 fn postBatch(allocator: Allocator, config: Config, events: []const ActorEvent, cursor: i64) bool { 247 228 var client = http.Client{ .allocator = allocator }; 248 229 defer client.deinit(); 249 230 250 - var body: std.ArrayList(u8) = .{}; 251 - defer body.deinit(allocator); 252 - 253 - var w = body.writer(allocator); 254 - w.writeAll("{\"events\":[") catch return false; 255 - 256 - for (events, 0..) |event, i| { 257 - if (i > 0) w.writeByte(',') catch return false; 258 - w.writeAll("{\"did\":\"") catch return false; 259 - w.writeAll(event.did) catch return false; 260 - w.writeByte('"') catch return false; 261 - if (event.handle) |h| { 262 - w.writeAll(",\"handle\":\"") catch return false; 263 - writeJsonEscaped(&w, h) catch return false; 264 - w.writeByte('"') catch return false; 265 - } 266 - if (event.display_name) |n| { 267 - w.writeAll(",\"display_name\":\"") catch return false; 268 - writeJsonEscaped(&w, n) catch return false; 269 - w.writeByte('"') catch return false; 270 - } 271 - if (event.avatar_cid) |c| { 272 - w.writeAll(",\"avatar_cid\":\"") catch return false; 273 - w.writeAll(c) catch return false; 274 - w.writeByte('"') catch return false; 275 - } 276 - w.writeByte('}') catch return false; 277 - } 231 + var output: std.Io.Writer.Allocating = .init(allocator); 232 + defer output.deinit(); 278 233 279 - w.print("],\"cursor\":{d}}}", .{cursor}) catch return false; 234 + var jw: json.Stringify = .{ 235 + .writer = &output.writer, 236 + .options = .{ .emit_null_optional_fields = false }, 237 + }; 238 + jw.write(.{ .events = events, .cursor = cursor }) catch return false; 280 239 281 240 var url_buf: [512]u8 = undefined; 282 241 const url = std.fmt.bufPrint(&url_buf, "{s}/admin/ingest", .{config.worker_url}) catch return false; ··· 284 243 var auth_buf: [256]u8 = undefined; 285 244 const auth = std.fmt.bufPrint(&auth_buf, "Bearer {s}", .{config.secret}) catch return false; 286 245 287 - var aw: std.Io.Writer.Allocating = .init(allocator); 288 - defer aw.deinit(); 246 + var resp_output: std.Io.Writer.Allocating = .init(allocator); 247 + defer resp_output.deinit(); 248 + 249 + const body = output.toArrayList(); 289 250 290 251 const result = client.fetch(.{ 291 252 .location = .{ .url = url }, ··· 295 256 .authorization = .{ .override = auth }, 296 257 }, 297 258 .payload = body.items, 298 - .response_writer = &aw.writer, 259 + .response_writer = &resp_output.writer, 299 260 }) catch return false; 300 261 301 262 if (result.status != .ok) { 302 - const resp = aw.toArrayList(); 263 + const resp = resp_output.toArrayList(); 303 264 log.err("ingest HTTP {d}: {s}", .{ @intFromEnum(result.status), resp.items }); 304 265 } 305 266 ··· 310 271 var client = http.Client{ .allocator = allocator }; 311 272 defer client.deinit(); 312 273 313 - var body: std.ArrayList(u8) = .{}; 314 - defer body.deinit(allocator); 274 + var output: std.Io.Writer.Allocating = .init(allocator); 275 + defer output.deinit(); 315 276 316 - var w = body.writer(allocator); 317 - w.writeAll("{\"dids\":[") catch return false; 318 - for (dids, 0..) |did, i| { 319 - if (i > 0) w.writeByte(',') catch return false; 320 - w.writeByte('"') catch return false; 321 - w.writeAll(did) catch return false; 322 - w.writeByte('"') catch return false; 323 - } 324 - w.writeAll("]}") catch return false; 277 + var jw: json.Stringify = .{ .writer = &output.writer }; 278 + jw.write(.{ .dids = dids }) catch return false; 325 279 326 280 var url_buf: [512]u8 = undefined; 327 281 const url = std.fmt.bufPrint(&url_buf, "{s}/admin/delete", .{config.worker_url}) catch return false; 328 282 329 283 var auth_buf: [256]u8 = undefined; 330 284 const auth = std.fmt.bufPrint(&auth_buf, "Bearer {s}", .{config.secret}) catch return false; 285 + 286 + const body = output.toArrayList(); 331 287 332 288 const result = client.fetch(.{ 333 289 .location = .{ .url = url },