server: every dns listener shares one budget of 32 queries, stream listeners take 16 connections, the task pool is capped from those bounds, and work it cannot start is counted by site

This commit is contained in:
2026-10-22 15:24:10 +02:00
parent e4e405f8e9
commit 63cc5f8dc3
23 changed files with 983 additions and 324 deletions
+1
View File
@@ -62,6 +62,7 @@ Within one source, as compiled entries, an exact `x` in `.list` together with `x
- UDP keeps today's counted drop when no permit is free (`dropped_no_slot`). The kernel buffer does not absorb overload invisibly.
- The upstream exchange keeps its whole-operation `Select` deadline and its distinction between peer result, budget expiry and cancellation. The thread high-water falls because the query budget is smaller, not because the race changes.
- UDP slots and TCP connection buffers are sized from these bounds, not 64 per listener.
- As built: 32 query permits for the whole process (`query_budget.permits`; the Pi's `nxdns_dns_in_flight_peak` was 27 over 37 h), each holding the datagram, the reply buffer and the handler scratch, about 2.4 MiB in all. 16 connections per DNS stream listener (`listener.dns_max_connections`), a policy rather than a measurement: the Pi's TCP peak was 0 and it runs neither DoT nor DoH. A stream query that finds no permit closes its connection and is counted as `dropped_no_permit`, on DoH too, where a 503 would need a reply buffer the query does not have. `async_limit` is `.nothing`, so every pool task is a counted `concurrent` one, and `app.concurrent_limit` enumerates them. `ConcurrencyUnavailable` is `nxdns_concurrency_unavailable_total{site}`, one label per boundary (`platform/concurrency.zig`).
### 4. Size the query-log buffers by use