atproto relay implementation in zig zlay.waow.tech
9
fork

Configure Feed

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

remove per-day host rate limit

the Go relay's HostPerDayLimiter (50/day default) was copied
wholesale, but it only makes sense there because it gates the
public requestCrawl endpoint while admin operations bypass it.

zlay applies it uniformly, blocking legitimate bulk seeding from
cronjobs. the other validation steps (hostname format, domain bans,
dedup, describeServer liveness) provide sufficient protection.

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

zzstoatzz 616325b0 78cf4cda

+1 -27
+1 -27
src/slurper.zig
··· 24 24 pub const Options = struct { 25 25 seed_host: []const u8 = "bsky.network", 26 26 max_message_size: usize = 5 * 1024 * 1024, 27 - new_hosts_per_day: u32 = 50, // Go relay: RELAY_NEW_HOSTS_PER_DAY_LIMIT default 50 28 27 }; 29 28 30 29 // --- host validation --- ··· 217 216 // crawl processing thread 218 217 crawl_thread: ?std.Thread = null, 219 218 220 - // per-day new host rate limit (Go relay: HostPerDayLimiter) 221 - hosts_added_today: u32 = 0, 222 - rate_limit_day_start: i64 = 0, 223 - 224 219 pub fn init( 225 220 allocator: Allocator, 226 221 bc: *broadcaster.Broadcaster, ··· 411 406 } 412 407 } 413 408 414 - // step 5: per-day rate limit for new hosts 415 - // Go relay: HostPerDayLimiter (sliding window, 50/day default) 416 - if (!self.checkHostRateLimit()) { 417 - log.warn("host {s}: new-hosts-per-day limit reached ({d}), rejecting", .{ hostname, self.options.new_hosts_per_day }); 418 - return; 419 - } 420 - 421 - // step 6: describeServer liveness check 409 + // step 5: describeServer liveness check 422 410 // Go relay: host_checker.go CheckHost (with SSRF protection) 423 411 checkHost(self.allocator, hostname) catch |err| { 424 412 log.warn("host {s}: describeServer check failed: {s}", .{ hostname, @errorName(err) }); ··· 427 415 428 416 try self.spawnWorker(host_info.id, hostname); 429 417 log.info("added host {s} (id={d})", .{ hostname, host_info.id }); 430 - } 431 - 432 - /// check and consume one token from the daily host rate limit. 433 - /// resets counter when a new UTC day starts. 434 - fn checkHostRateLimit(self: *Slurper) bool { 435 - const now = std.time.timestamp(); 436 - const day_seconds: i64 = 86400; 437 - if (now - self.rate_limit_day_start >= day_seconds) { 438 - self.hosts_added_today = 0; 439 - self.rate_limit_day_start = now; 440 - } 441 - if (self.hosts_added_today >= self.options.new_hosts_per_day) return false; 442 - self.hosts_added_today += 1; 443 - return true; 444 418 } 445 419 446 420 /// spawn a subscriber thread for a host