polls on atproto
pollz.waow.tech
atproto
zig
zig 0.15 notes#
reference for zig 0.15 patterns used in the backend.
breaking changes from 0.14#
json.stringify → json.fmt#
// old: json.stringify(value, .{}, writer);
// new: use json.fmt formatter
try buffer.print(allocator, "{f}", .{json.fmt(value, .{})});
std.ArrayList is unmanaged by default#
// old 0.14 style:
var list = std.ArrayList(u8).init(allocator);
try list.appendSlice("hello");
list.deinit();
// new 0.15 style:
var list: std.ArrayList(u8) = .{};
try list.appendSlice(allocator, "hello");
list.deinit(allocator);
std.time.sleep removed#
// use posix.nanosleep instead
std.posix.nanosleep(seconds, nanoseconds);
std.Uri.percentDecode → percentDecodeInPlace#
// copy to mutable buffer first, then decode in place
const uri_buf = try alloc.dupe(u8, uri_encoded);
const uri = std.Uri.percentDecodeInPlace(uri_buf);
http server patterns#
net.Stream → http.Server#
var read_buffer: [8192]u8 = undefined;
var write_buffer: [8192]u8 = undefined;
var reader = conn.stream.reader(&read_buffer);
var writer = conn.stream.writer(&write_buffer);
var server = http.Server.init(reader.interface(), &writer.interface);
responding to requests#
try request.respond(body, .{
.status = .ok,
.extra_headers = &.{
.{ .name = "content-type", .value = "application/json" },
},
});
websocket client (karlseguin/websocket.zig)#
const websocket = @import("websocket");
var client = try websocket.Client.init(allocator, .{
.host = "example.com",
.port = 443,
.tls = true,
});
defer client.deinit();
// Host header must be provided manually
client.handshake("/path", .{ .headers = "Host: example.com\r\n" }) catch |err| {
// handle error
};
// handler must have serverMessage(self, data) function
var handler = MyHandler{};
try client.readLoop(&handler);
sqlite patterns (zqlite)#
prepared statements with bind#
var stmt = conn.prepare("SELECT * FROM votes WHERE uri = ?") catch return;
defer stmt.deinit();
const row = stmt.bind(.{uri}).step() catch return;
if (row) |r| {
const subject = r[0].?.text;
// ...
}
upsert with ON CONFLICT#
conn.exec(
\\INSERT INTO votes (uri, subject, option, voter, created_at)
\\VALUES (?, ?, ?, ?, ?)
\\ON CONFLICT(subject, voter) DO UPDATE SET
\\ uri = excluded.uri,
\\ option = excluded.option,
\\ created_at = excluded.created_at
\\WHERE excluded.created_at > votes.created_at OR votes.created_at IS NULL
, .{ uri, subject, option, voter, created_at }) catch |err| {
// handle error
};
build.zig.zon#
.{
.name = .pollz,
.version = "0.0.0",
.fingerprint = 0x..., // required in 0.15
.dependencies = .{
.zqlite = .{ ... },
.websocket = .{ ... },
},
}