polls on atproto
pollz.waow.tech
atproto
zig
1const std = @import("std");
2const posix = std.posix;
3const Thread = std.Thread;
4const Io = std.Io;
5const net = Io.net;
6const db = @import("db.zig");
7const http_server = @import("http.zig");
8const jetstream = @import("jetstream.zig");
9
10// socket timeout in seconds
11const SOCKET_TIMEOUT_SECS = 30;
12
13// Threaded Io instance — initialized in main() before any threads are spawned.
14// Override debug_threaded_io so std.debug.print is multi-thread safe.
15var app_threaded_io: Io.Threaded = undefined;
16pub const std_options_debug_threaded_io: ?*Io.Threaded = &app_threaded_io;
17
18pub fn main() !void {
19 const allocator = std.heap.smp_allocator;
20
21 app_threaded_io = Io.Threaded.init(allocator, .{});
22 const io = app_threaded_io.io();
23
24 // init sqlite
25 const db_path: [*:0]const u8 = if (std.c.getenv("DATA_PATH")) |p| p else "/data/pollz.db";
26 try db.init(io, db_path);
27 defer db.close();
28
29 // init http module with io
30 http_server.init(io);
31
32 // backfill any voter profiles missing from cache
33 const backfill_thread = try Thread.spawn(.{}, http_server.backfillVoterProfiles, .{});
34 backfill_thread.detach();
35
36 // start jetstream consumer in background
37 const js_thread = try Thread.spawn(.{}, jetstream.start, .{ io, allocator });
38 js_thread.detach();
39
40 // start http server
41 var address = try net.IpAddress.parse("::", 3000);
42 var server = try net.IpAddress.listen(&address, io, .{ .reuse_address = true });
43 defer server.deinit(io);
44
45 std.debug.print("pollz backend listening on http://[::]:3000\n", .{});
46
47 while (true) {
48 const stream = server.accept(io) catch |err| {
49 std.debug.print("accept error: {}\n", .{err});
50 continue;
51 };
52
53 setSocketTimeout(stream.socket.handle, SOCKET_TIMEOUT_SECS) catch |err| {
54 std.debug.print("failed to set socket timeout: {}\n", .{err});
55 };
56
57 const t = Thread.spawn(.{}, http_server.handleConnection, .{stream}) catch |err| {
58 std.debug.print("spawn error: {}\n", .{err});
59 stream.close(io);
60 continue;
61 };
62 t.detach();
63 }
64}
65
66fn setSocketTimeout(fd: posix.fd_t, secs: u32) !void {
67 const timeout = std.mem.toBytes(posix.timeval{
68 .sec = @intCast(secs),
69 .usec = 0,
70 });
71 try posix.setsockopt(fd, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout);
72 try posix.setsockopt(fd, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout);
73}