Prerequisites. You can read C and know what a UDP socket is. Building requires Linux, a C11 compiler, OpenSSL development files, and Make or CMake. Everything else is explained here.
Linux epoll drives a request that combines a resource rate limit with a
pre-work latency guard. Allowed work is measured afterward and reported as one
latency sample; denied, cancelled, or failed work produces no sample.
This example uses Linux epoll directly—no event-loop library. It registers
the public runtime’s nonblocking UDP sockets for EPOLLIN and derives every
epoll_wait timeout from the current admission deadline.
The request contains both controls: the resource rate limit protects capacity, while the latency guard checks existing tracker history before work starts. On the allowed path, the example constructs a response synchronously, measures only that work with a monotonic clock, and sends the completed duration back to the same latency tracker.
Build the library from the repository root, then run either build path here:
make -C ../..
make
./epoll-example
cmake -S . -B build
cmake --build build
./build/epoll-example
An allowed run prints allowed: ...; latency=... ms. A policy denial exits
with status 2 and names the rate limit, latency guard, or both.
RATELIMITLY_AUTH_KEY is required. With no overrides, the runtime decodes the
key ID, derives c-<key-id>.p0.ratelimitly.com, and discovers the production
SRV record _ratelimitly._udp.c-<key-id>.p0.ratelimitly.com.
RATELIMITLY_TENANT optionally replaces the derived tenant DNS name. For a
fixed development responder, set RATELIMITLY_EXAMPLE_SERVER_HOST and
RATELIMITLY_EXAMPLE_SERVER_PORT together; setting only one is invalid. Leave
all three overrides unset for key-derived P0 discovery.
export RATELIMITLY_AUTH_KEY='rl-aes1...'
# Optional fixed development endpoint; set both or neither.
export RATELIMITLY_EXAMPLE_SERVER_HOST=127.0.0.1
export RATELIMITLY_EXAMPLE_SERVER_PORT=39082
./epoll-example
flowchart TD
Start["Start resource + latency admission"] --> Register["Register UDP sockets for EPOLLIN"]
Register --> Delay["Compute current admission timeout"]
Delay --> Wait["epoll_wait"]
Wait --> Result{"Ready events or timeout?"}
Result -->|EPOLLIN| Read["Drain runtime datagrams"]
Result -->|Timeout| Timeout["Advance admission timeout"]
Read --> Decision{"Admission complete?"}
Timeout --> Decision
Decision -->|No| Delay
Decision -->|Denied| Reject["No protected work or sample"]
Decision -->|Allowed| Work["Run work, measure, report latency"]
The latency guard is an admission decision based on tracker history already at
the server; it does not measure the operation waiting to run. After both the
guard and rate limit allow the request, r_runtime_admission_run_and_report()
measures prepare_response() and sends one post-work sample. It suppresses a
sample when admission is denied or when work is cancelled or fails.
The synchronous callback keeps this teaching program short. Production event
loops should start nonblocking work after admission, retain the request and a
monotonic start time, then report once from the successful completion callback;
do not block the epoll thread or report when asynchronous work is merely
scheduled.
epoll is a Linux kernel API, so this folder intentionally supports Linux
only. Ubuntu CI runs allow, resource-denial, and latency-denial scenarios
against the synthetic responder and verifies exact request/report pairing.
Trusted main runs also exercise key-derived production P0 discovery and
admission; because a latency report is a UDP send, that smoke test proves the
local send path, not server receipt of each report.
For production, treat EPOLLERR and EPOLLHUP as watcher failures, recompute
the timeout after every client transition, keep request storage alive until
callback or cancellation, and close the epoll descriptor before destroying the
runtime-owned sockets.
| Term | Meaning |
|---|---|
epoll |
Linux readiness API that waits for activity on registered file descriptors. |
| admission deadline | Next time the client must advance request timeout or retry state. |
| latency guard | Pre-work policy check against existing samples for the configured service. |
| latency sample | Post-work duration reported after one admitted operation completes successfully. |
| SRV | DNS service record that supplies a host and port. |