# `TypeSafeSDK.OTP.Server`
[🔗](https://github.com/nshkrdotcom/typesafe_sdk/blob/v0.4.0/lib/typesafe_sdk/otp/server.ex#L1)

Bounded OTP facade for asynchronous TypeSafe evaluations inside a GenServer.

`use TypeSafeSDK.OTP.Server` keeps ordinary GenServer callbacks in the caller
module and adds one callback, `handle_evaluation/3`. Return
`{:evaluate, {tag, state, questions}, inner_state}` (or the four-element form
with per-request options) from a callback to start an evaluation without
blocking the server. The eventual `{:ok, response}` / `{:error, error}` result
is delivered to `handle_evaluation/3` with the same opaque tag.

This module deliberately does **not** start a global supervisor or own an HTTP
runtime. Callers provide a `Task.Supervisor` from their application tree and a
normal `TypeSafeSDK.Client`. `max_in_flight` bounds pending evaluations for the
server. TypeSafeSDK still delegates HTTP, retries and physical cancellation to
Pristine.

The wrapper scopes every request with its own private `Pristine.Cancellation`
token. When the caller supplies a cancellation token, a temporary watcher mirrors
caller cancellation into the private token without mutating caller-owned state.
On server shutdown the private token is cancelled before the local task is stopped.

# `async_result`

```elixir
@type async_result(state) ::
  {:evaluate, evaluation_request(), state}
  | {:noreply, state}
  | {:noreply, state, timeout() | :hibernate | {:continue, term()}}
  | {:stop, term(), state}
```

Return values accepted from asynchronous delegated callbacks.

# `call_result`

```elixir
@type call_result(state) ::
  async_result(state)
  | {:reply, term(), state}
  | {:reply, term(), state, timeout() | :hibernate | {:continue, term()}}
  | {:stop, term(), term(), state}
```

Return values accepted from `handle_call/3`.

# `evaluation_request`

```elixir
@type evaluation_request() ::
  {tag(), term(), term()} | {tag(), term(), term(), keyword()}
```

A request started by a callback without blocking the server.

# `tag`

```elixir
@type tag() :: term()
```

An opaque correlation term returned unchanged to `handle_evaluation/3`.

# `code_change`
*optional* 

```elixir
@callback code_change(term() | {:down, term()}, term(), term()) ::
  {:ok, term()} | {:error, term()}
```

# `handle_call`
*optional* 

```elixir
@callback handle_call(term(), GenServer.from(), term()) :: call_result(term())
```

# `handle_cast`
*optional* 

```elixir
@callback handle_cast(term(), term()) :: async_result(term())
```

# `handle_continue`
*optional* 

```elixir
@callback handle_continue(term(), term()) :: async_result(term())
```

# `handle_evaluation`

```elixir
@callback handle_evaluation({:ok, term()} | {:error, term()}, tag(), term()) ::
  async_result(term())
```

# `handle_info`
*optional* 

```elixir
@callback handle_info(term(), term()) :: async_result(term())
```

# `init`

```elixir
@callback init(term()) ::
  {:ok, term()}
  | {:ok, term(), timeout() | :hibernate | {:continue, term()}}
  | {:stop, term()}
  | :ignore
```

# `terminate`
*optional* 

```elixir
@callback terminate(term(), term()) :: term()
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `start_link`

```elixir
@spec start_link(module(), keyword()) :: GenServer.on_start()
```

Start a wrapped module.

Required options are `:client` and `:task_supervisor`. Optional wrapper options
are `:init_arg`, `:max_in_flight` (default 32), and `:evaluation_options`.
Standard GenServer start options such as `:name` are also accepted.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
