at main 2.4 kB view raw
1const std = @import("std"); 2const net = std.net; 3const posix = std.posix; 4const Thread = std.Thread; 5 6const http = @import("server/http.zig"); 7const db = @import("store/db.zig"); 8const jetstream = @import("jetstream.zig"); 9const stats = @import("server/stats.zig"); 10 11const log = std.log.scoped(.main); 12 13const MAX_HTTP_WORKERS = 16; 14const SOCKET_TIMEOUT_SECS = 30; 15 16pub fn main() !void { 17 var gpa = std.heap.GeneralPurposeAllocator(.{ 18 .thread_safe = true, 19 }){}; 20 defer _ = gpa.deinit(); 21 const allocator = gpa.allocator(); 22 23 // init stats 24 stats.init(); 25 26 // init database 27 try db.init(); 28 29 // start jetstream consumer in background (runs forever, reconnects on error) 30 const js_thread = try Thread.spawn(.{}, jetstream.consumer, .{allocator}); 31 js_thread.detach(); 32 33 // init thread pool for http connections 34 var pool: Thread.Pool = undefined; 35 try pool.init(.{ 36 .allocator = allocator, 37 .n_jobs = MAX_HTTP_WORKERS, 38 }); 39 defer pool.deinit(); 40 41 // start http server 42 const port: u16 = blk: { 43 const port_str = posix.getenv("PORT") orelse "3000"; 44 break :blk std.fmt.parseInt(u16, port_str, 10) catch 3000; 45 }; 46 47 const address = try net.Address.parseIp("0.0.0.0", port); 48 var server = try address.listen(.{ .reuse_address = true }); 49 defer server.deinit(); 50 51 log.info("listening on http://0.0.0.0:{d}", .{port}); 52 53 while (true) { 54 const conn = server.accept() catch |err| { 55 log.err("accept error: {}", .{err}); 56 continue; 57 }; 58 59 setSocketTimeout(conn.stream.handle, SOCKET_TIMEOUT_SECS) catch |err| { 60 log.warn("failed to set socket timeout: {}", .{err}); 61 }; 62 63 pool.spawn(http.handleConnection, .{conn}) catch |err| { 64 log.err("pool spawn error: {}", .{err}); 65 conn.stream.close(); 66 }; 67 } 68} 69 70fn setSocketTimeout(fd: posix.fd_t, secs: u32) !void { 71 const timeout = std.mem.toBytes(posix.timeval{ 72 .sec = @intCast(secs), 73 .usec = 0, 74 }); 75 try posix.setsockopt(fd, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout); 76 try posix.setsockopt(fd, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout); 77} 78 79test { 80 _ = @import("feed/filter.zig"); 81 _ = @import("feed/skeleton.zig"); 82 _ = @import("server/stats.zig"); 83 _ = @import("store/posts.zig"); 84}