search for standard sites pub-search.waow.tech
search zig blog atproto

fix: move schema init to background thread to prevent startup hangs

zig 0.15 stdlib http.Client has no timeout support. When turso is
slow/unreachable, schema.init() blocks the main thread indefinitely,
preventing the accept loop from ever starting. Move schema migrations
to the background initServices thread so the server can accept
connections immediately.

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

+15 -2
+12 -2
backend/src/db/mod.zig
··· 18 18 var sync_client: ?Client = null; 19 19 var local_db: ?LocalDb = null; 20 20 21 - /// Initialize Turso client only (fast, call synchronously at startup) 21 + /// Initialize Turso client only (fast, call synchronously at startup). 22 + /// Schema migrations run separately via initSchema() in the background thread 23 + /// so a slow/unreachable turso doesn't block the accept loop. 22 24 pub fn initTurso() !void { 23 25 client = try Client.init(gpa.allocator()); 24 26 sync_client = try Client.init(gpa.allocator()); 25 - try schema.init(&client.?); 27 + } 28 + 29 + /// Run schema migrations (idempotent). Call from background thread. 30 + pub fn initSchema() void { 31 + if (client) |*c| { 32 + schema.init(c) catch |err| { 33 + std.debug.print("schema init failed (tables likely already exist): {}\n", .{err}); 34 + }; 35 + } 26 36 } 27 37 28 38 /// Initialize local SQLite replica (slow, call in background thread)
+3
backend/src/main.zig
··· 73 73 } 74 74 75 75 fn initServices(allocator: std.mem.Allocator) void { 76 + // run schema migrations first (idempotent, but may be slow if turso is laggy) 77 + db.initSchema(); 78 + 76 79 // init local db (slow - turso already initialized) 77 80 db.initLocalDb(); 78 81 db.startSync();