# Serving

> UCall for Mojo

A handler is a compile-time parameter of its route, `server.get["/users/{name}", handler]()` and likewise `post`, `put`, `delete` and `patch`, or `route[path, handler](verb)` and `route_with[path, handler](verb, delivery)` for any other.

UCall writes nothing on its own; a server's or a client's `log` option hands every line to a handler, with state of your own that must outlive the server or client:

```mojo
def count(level: LogLevel, line: StringSlice[ImmUntrackedOrigin], mut lines: Int):
    lines += 1

var options = ServerOptions()
options.log = Log.to[count](lines, level=LogLevel.INFO)
```

`from ucall import Interface, Metrics, ServerOptions, …`

## Interface

One address the server answers on, with the security and admission limits of what arrives there.

```mojo
struct Interface
```

Several live under one server, so it may answer plaintext on loopback and Noise on the wire at once.

- `address` `String`: Listening address in "host:port" form; port zero picks a free one, which [`Server.address`](#address) reports.
- `listen_descriptor` `Optional[Int]`: A listening stream socket another owner opened, accepted on instead of binding [`address`](#address).
- `device_name` `String`: A physical device to pin the interface to, like "eth0", on Linux only; empty binds by address.
- `security` `Security`: Encryption for connections accepted here; [`NOISE_XX`](https://www.unum.cloud/docs/ucall/mojo/noise-keys.md#NOISE_XX) also needs `peer_authorizer`.
- `noise_private_key` `Optional[SIMD[.uint8, 32]]`: The server identity for handshakes, required unless `security` is [`NONE`](https://www.unum.cloud/docs/ucall/mojo/noise-keys.md#NONE).
- `noise_peer_key` `Optional[SIMD[.uint8, 32]]`: The one initiator's static public key a [`NOISE_KK`](https://www.unum.cloud/docs/ucall/mojo/noise-keys.md#NOISE_KK) interface admits.
- `peer_authorizer` `PeerAuthorizer`: Vets each client's authenticated static key before any of its requests is read.
- `event_loops` `Int`: Event loops accepting here; zero means one, or the receive-queue count of a named device.
- `connections` `Int`: Connections open at once across this interface's loops.
- `pipelined_requests` `Int`: Requests one connection may have in flight before the server stops reading it; zero means one.
- `max_request_bytes` `Int`: The largest request head and buffered body; zero takes the largest socket receive buffer.
- `reply_directories` `List[String]`: Directories the path parts of replies to this interface's requests resolve beneath, by position.

Conforms to: `Copyable`, `Deinitable`, `Movable`

## __init__

An interface listening on [`address`](#address) with the default security and limits.

```mojo
def __init__(out self, address: String, *, connections: Int = Int(1024), event_loops: Int = Int(0))
```

- `address`: Where to listen, in "host:port" form.
- `connections`: Connections open at once.
- `event_loops`: Event loops accepting here; zero means one.

## Metrics

The StatsD endpoint a server sends each event loop's counters and sampled latencies to.

```mojo
struct Metrics
```

- `address` `String`: The endpoint in "host:port" form; empty sends nothing.
- `sample_rate` `Float32`: The fraction of finished requests whose latency is reported, in (0, 1]; zero means 1.
- `prefix` `String`: The metric name prefix; empty means "ucall".
- `tags` `List[String]`: Tags on every metric, each "key:value".
- `interval_microseconds` `Int`: The time between one event loop's datagrams; zero means one second.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `Movable`

## __init__

No endpoint, so no datagram leaves.

```mojo
def __init__(out self)
```

## ServerOptions

What a server runs on and reports through, beside its interfaces.

```mojo
struct ServerOptions
```

- `backend` `Backend`: The requested I/O backend, failing rather than substituting when it is unavailable.
- `cpu_class` `CPUClass`: A ceiling on the CPU class; [`UNKNOWN`](https://www.unum.cloud/docs/ucall/mojo/threads-and-polling.md#UNKNOWN) takes what the constructing thread's CPU offers.
- `log` `Log`: Where log lines go; the default keeps the server silent.
- `metrics` `Metrics`: Where StatsD datagrams go; the default sends none.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `Movable`

## __init__

The automatic backend and CPU class, silent and without metrics.

```mojo
def __init__(out self)
```

## EventLoopStatistics

Counters of one event loop since the server started, `ucall_event_loop_statistics_t` in C.

```mojo
struct EventLoopStatistics
```

Divided by `requests`, they price one call. Each counter is read on its own, so a snapshot of a
running loop is not one instant.

- `polls` `UInt64`: Engine polls the loop issued, each taking zero or more completions.
- `empty_polls` `UInt64`: Engine polls that took no completion.
- `kernel_enters` `UInt64`: System calls: io_uring enters, or other backends' waits, registrations and socket calls.
- `submissions` `UInt64`: Operations queued.
- `completions` `UInt64`: Results taken.
- `cancellations` `UInt64`: Pending operations, or io_uring multishot receives, the engine asked to cancel.
- `accepts` `UInt64`: Connections accepted and handed to this loop.
- `requests` `UInt64`: HTTP requests parsed and dispatched to an endpoint or an error reply.
- `receive_rearms` `UInt64`: Multishot receives armed again on a socket that already streamed.
- `bytes_received` `UInt64`: Bytes the kernel reported received, ciphertext under Noise.
- `bytes_sent` `UInt64`: Bytes the kernel reported sent, ciphertext under Noise.
- `bytes_copied` `UInt64`: Bytes UCall copied: receive appends, reply bodies, Noise records and parked receives.
- `zero_copy_sends` `UInt64`: Sends that left without copying.
- `zero_copy_fallbacks` `UInt64`: Zero-copy sends the kernel copied anyway or refused to pin.
- `copying_sends` `UInt64`: Sends that copied instead of pinning.
- `file_reads_asynchronous` `UInt64`: File reads the kernel finishes later.
- `file_reads_blocking` `UInt64`: File reads the loop issued itself and blocked on.
- `bytes_read` `UInt64`: Bytes the kernel reported read from files into the loop's file windows.
- `file_window_overlaps` `UInt64`: File reads submitted while an earlier window of the same stream waited to send or sent.
- `linger_resets` `UInt64`: Lingering closes reset at their deadline because the kernel still held what they sent.
- `ready_passes` `UInt64`: Passes the loop made over a ready connection.
- `replied_dequeues` `UInt64`: Replied exchanges the loop took from its queue to adopt their reply segments.
- `refused_requests` `UInt64`: Requests the loop answered itself with 400, 404, 405, 413, 501, 503 or 505.
- `handshake_failures` `UInt64`: Connections whose Noise handshake failed.
- `authorizer_refusals` `UInt64`: Connections whose authenticated peer key the interface's authorizer refused.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## __init__

Every counter at zero, as a failed read leaves them.

```mojo
def __init__(out self)
```

## BatchEndpointStatistics

Counters of one batch endpoint since registration, `ucall_batch_endpoint_statistics_t` in C.

```mojo
struct BatchEndpointStatistics
```

- `batches` `UInt64`: Batches handed to the handler.
- `requests` `UInt64`: Requests across those batches.
- `filled_batches` `UInt64`: Batches dispatched on reaching [`Batching.max_size`](https://www.unum.cloud/docs/ucall/mojo/batches.md#Batching).
- `ready_batches` `UInt64`: Batches dispatched on reaching [`Batching.min_size`](https://www.unum.cloud/docs/ucall/mojo/batches.md#Batching), below the maximum.
- `expired_batches` `UInt64`: Batches dispatched below [`Batching.min_size`](https://www.unum.cloud/docs/ucall/mojo/batches.md#Batching) once [`Batching.max_latency_microseconds`](https://www.unum.cloud/docs/ucall/mojo/batches.md#Batching) passed.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## __init__

Every counter at zero, as a failed read leaves them.

```mojo
def __init__(out self)
```

## Server

An HTTP server over one or more interfaces, polled by application threads.

```mojo
struct Server
```

Register every endpoint first, then poll each event loop from one thread at a time. Not
`Movable`, as every route hands the library this server's address. Dropping it stops the server;
the library frees it once the last batch endpoint and detached request are gone too.

- `shared` `ArcPointer[_ServerCore]`: The handle, shared with batch endpoints and detached requests.

Conforms to: `Deinitable`, `Movable`

## __init__

Starts a server answering on `interfaces`. Calls `ucall_server_init`.

```mojo
def __init__(
    out self,
    library: Library,
    interfaces: Span[Interface],
    options: ServerOptions = ServerOptions()
)
```

- `library`: The loaded library, kept so the shared object stays mapped.
- `interfaces`: At least one interface; their addresses, keys and directories are copied.
- `options`: The backend, CPU class, log sink and StatsD endpoint.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) if an interface is unusable, no backend serves the configuration, or an address cannot be bound.

## __deinit__

Stops the server, which the library frees once nothing else holds it.

```mojo
def __deinit__(deinit self)
```

## event_loops

Event loops this server runs, each to be polled by one thread at a time. Binding-only.

```mojo
def event_loops(self) -> Int
```

## backend

The I/O backend the server resolved to. Binding-only.

```mojo
def backend(self) -> Backend
```

## cpu_class

The CPU class the server resolved to. Binding-only.

```mojo
def cpu_class(self) -> CPUClass
```

## address

The numeric address interface `index` listens on, with the port it bound. Binding-only.

```mojo
def address(self, index: Int) -> Optional[String]
```

- `index`: The interface's position among those the server was started with.

## route

Routes requests matching [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) and [`verb`](https://www.unum.cloud/docs/ucall/mojo/requests.md#verb) to `handler`, which runs on the polling thread. Calls `ucall_server_add_http_endpoint`.

```mojo
def route[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](
    mut self,
    verb: Verb
)
```

Templates capture `{name}` segments and a greedy `{*name}` tail, read back through
[`path_parameter`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path_parameter). A handler that raises, or leaves its request unreplied, answers 500.

- `path` (comptime): The URI template.
- `handler` (comptime): Receives each matching request, owned from then on.
- `verb`: The HTTP method, or [`Verb.ANY`](#ANY).

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`ALREADY_EXISTS`](https://www.unum.cloud/docs/ucall/mojo/errors.md#ALREADY_EXISTS) for a template and verb registered before, or [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/ucall/mojo/errors.md#INVALID_ARGUMENT) for a malformed template.

## route_with

Routes like [`route`](#route), running `handler` once the body is buffered, or with [`STREAMED`](https://www.unum.cloud/docs/ucall/mojo/batches.md#STREAMED) as soon as the headers arrived. Calls `ucall_server_add_http_endpoint`.

```mojo
def route_with[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](
    mut self,
    verb: Verb,
    delivery: BodyDelivery
)
```

- `path` (comptime): The URI template.
- `handler` (comptime): Receives each matching request, owned from then on.
- `verb`: The HTTP method, or [`Verb.ANY`](#ANY).
- `delivery`: When the handler runs.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) as [`route`](#route) does.

## get

Routes GET requests on [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) to `handler`. Calls `ucall_server_add_http_endpoint`.

```mojo
def get[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](mut self)
```

## post

Routes POST requests on [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) to `handler`. Calls `ucall_server_add_http_endpoint`.

```mojo
def post[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](mut self)
```

## put

Routes PUT requests on [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) to `handler`. Calls `ucall_server_add_http_endpoint`.

```mojo
def put[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](mut self)
```

## delete

Routes DELETE requests on [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) to `handler`. Calls `ucall_server_add_http_endpoint`.

```mojo
def delete[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](
    mut self
)
```

## patch

Routes PATCH requests on [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) to `handler`. Calls `ucall_server_add_http_endpoint`.

```mojo
def patch[path: StringSpan[ImmStaticOrigin], handler: def(var Request) raises thin -> None](
    mut self
)
```

## batch

Collects requests matching [`path`](https://www.unum.cloud/docs/ucall/mojo/requests.md#path) and [`verb`](https://www.unum.cloud/docs/ucall/mojo/requests.md#verb) from every event loop into one queue, which the returned endpoint drains into `handler`. Calls `ucall_server_add_http_batch_endpoint`.

```mojo
def batch[path: StringSpan[ImmStaticOrigin], handler: def(Batch) raises thin -> None](
    mut self,
    verb: Verb,
    batching: Batching = Batching()
) -> BatchEndpoint
```

Requests the handler does not take answer 500 once it returns.

- `path` (comptime): The URI template.
- `handler` (comptime): Receives each due batch, lent for the call.
- `verb`: The HTTP method, or [`Verb.ANY`](#ANY).
- `batching`: When a batch is due.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) as [`route`](#route) does, or with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/ucall/mojo/errors.md#INVALID_ARGUMENT) for a minimum above the maximum.

## take_call

Advances one event loop, running the handlers of the requests it completes on this thread, and waits up to `timeout_microseconds` for progress. Calls `ucall_server_take_call`.

```mojo
def take_call(self, event_loop: Int, timeout_microseconds: Int = Int(0)) -> Polling
```

- `event_loop`: The loop's index; each has one polling thread at a time.
- `timeout_microseconds`: The longest wait; zero performs one nonblocking round.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/ucall/mojo/errors.md#INVALID_ARGUMENT) past the last loop, or for an I/O failure.

## take_calls

Drives one event loop on this thread until [`stop`](#stop) or an I/O failure. Calls `ucall_server_take_calls`.

```mojo
def take_calls(self, event_loop: Int)
```

- `event_loop`: The loop's index; each has one polling thread at a time.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/ucall/mojo/errors.md#INVALID_ARGUMENT) past the last loop, or for an I/O failure.

## stop

Requests shutdown and wakes every polling thread, from any thread or handler. Calls `ucall_server_stop`.

```mojo
def stop(self)
```

The first call drains the requests already held; a second one cuts the replies in flight.

## event_loop_statistics

A snapshot of one event loop's counters, readable from any thread while it is polled. Calls `ucall_server_event_loop_statistics`.

```mojo
def event_loop_statistics(self, event_loop: Int) -> EventLoopStatistics
```

- `event_loop`: The loop's index.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/ucall/mojo/errors.md#INVALID_ARGUMENT) past the last loop.

## BatchEndpoint

One batch endpoint, polled by one thread at a time and observable from any.

```mojo
struct BatchEndpoint
```

Requests from every event loop share its queue, so one thread drains what all of them received.

Conforms to: `Deinitable`, `Movable`

## __init__

```mojo
def __init__(out self, var state: OwnedPointer[_BatchState], handle: Int)
```

## take_batch

Runs the handler on this thread if a batch is due, waiting up to `timeout_microseconds` for one. Calls `ucall_server_take_batch`.

```mojo
def take_batch(self, timeout_microseconds: Int = Int(0))
```

- `timeout_microseconds`: The longest wait; zero performs one nonblocking round.

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) if the library refuses the round.

## take_batches

Runs the handler on this thread for every due batch until [`Server.stop`](#stop). Calls `ucall_server_take_batches`.

```mojo
def take_batches(self)
```

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) if the library refuses the polling.

## statistics

A snapshot of the endpoint's counters, readable from any thread while it is polled. Calls `ucall_server_batch_endpoint_statistics`.

```mojo
def statistics(self) -> BatchEndpointStatistics
```

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) if the library refuses the read.

## Verb

An HTTP method, for routing and for client calls, `ucall_verb_t` in C.

```mojo
struct Verb
```

- `UNKNOWN` = `Verb(Int32(0))`: Unrecognized or not yet parsed.
- `GET` = `Verb(Int32(1))`: Retrieves a resource.
- `POST` = `Verb(Int32(2))`: Creates a resource.
- `PUT` = `Verb(Int32(3))`: Updates a resource.
- `DELETE` = `Verb(Int32(4))`: Removes a resource.
- `PATCH` = `Verb(Int32(5))`: Updates part of a resource.
- `HEAD` = `Verb(Int32(6))`: Retrieves headers only.
- `OPTIONS` = `Verb(Int32(7))`: Retrieves the supported methods.
- `ANY` = `Verb(Int32(8))`: Matches every method; valid only when registering an endpoint.
- `code` `c_int`: The raw `ucall_verb_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## Backend

A concrete I/O implementation, `ucall_io_backend_t` in C. [`Library.io_backend_name`](https://www.unum.cloud/docs/ucall/mojo/design.md#io_backend_name) spells each one.

```mojo
struct Backend
```

- `AUTOMATIC` = `Backend(Int32(0))`: The fastest backend this machine and its limits allow.
- `POSIX` = `Backend(Int32(1))`: Blocking sockets and files, polled with `poll`, on any POSIX system.
- `LINUX_EPOLLAIO` = `Backend(Int32(2))`: Linux epoll for sockets and Linux AIO for files, where io_uring is blocked.
- `LINUX_URING612` = `Backend(Int32(3))`: Linux io_uring as of 6.12, the older LTS line.
- `LINUX_URING618` = `Backend(Int32(4))`: Linux io_uring as of 6.18, the newer LTS line, with multishot receives.
- `BSD_KQUEUE` = `Backend(Int32(5))`: BSD kqueue on FreeBSD, with FreeBSD AIO for files, and on macOS.
- `WINDOWS_IOCP` = `Backend(Int32(6))`: I/O completion ports on Windows.
- `code` `c_int`: The raw `ucall_io_backend_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## LogLevel

Severity of a log line, from the most verbose up, `ucall_log_level_t` in C.

```mojo
struct LogLevel
```

- `DEBUG` = `LogLevel(Int32(0))`: Detail for debugging.
- `INFO` = `LogLevel(Int32(1))`: Normal lifecycle events.
- `WARNING` = `LogLevel(Int32(2))`: Something unexpected that the library recovered from.
- `ERROR` = `LogLevel(Int32(3))`: An operation failed.
- `FATAL` = `LogLevel(Int32(4))`: The server or client cannot continue.
- `code` `c_int`: The raw `ucall_log_level_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## LogFormat

Shape of each log line, `ucall_log_format_t` in C.

```mojo
struct LogFormat
```

- `HUMAN` = `LogFormat(Int32(0))`: Human-readable unit-normalized lines.
- `JSON` = `LogFormat(Int32(1))`: Newline-delimited JSON documents.
- `code` `c_int`: The raw `ucall_log_format_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## Log

The single log sink of a client or a server, `ucall_log_t` in C; the default logs nothing.

```mojo
struct Log
```

- `callback` `Address`: The `ucall_log_callback_t` every line at or above `level` goes to; `NULL_ADDRESS` logs nothing.
- `context` `Address`: The state `callback` writes into, passed verbatim.
- `format` `LogFormat`: Line format.
- `level` `LogLevel`: Lines below this severity are never formatted.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## __init__

No sink, so the library stays silent.

```mojo
def __init__() -> Self
```

## to

A sink calling `handler` with every line at or above `level`, on whichever thread made it.

```mojo
def to[State: AnyType, //, handler: def(LogLevel, StringSpan[ImmUntrackedOrigin], mut State) thin -> None](
    mut state: State,
    level: LogLevel = LogLevel.DEBUG,
    format: LogFormat = LogFormat.HUMAN
) -> Self
```

- `State` (comptime): The state's type, inferred from the argument.
- `handler` (comptime): Receives the severity, the line borrowed for the call without a newline, and the state.
- `state` (mut): What `handler` writes into; it must outlive the client or server, which keep its address.
- `level`: Lines below this severity are never formatted.
- `format`: Line format.

