# `SuperCache.Buffer`
[🔗](https://github.com/ohhi-vn/super_cache/blob/main/lib/buffer/buffer.ex#L1)

Manages per-scheduler write buffers used by `SuperCache.lazy_put/1`.

SuperCache creates one buffer process per online scheduler so that producers
can enqueue data without cross-scheduler contention. Each buffer runs a
continuous stream that pulls items from an internal queue and writes them
into the cache.

## Design

- **Scheduler affinity** — `enqueue/1` uses `:erlang.system_info(:scheduler_id)`
  to route data to the buffer running on the same scheduler, minimising
  context switches and cache-line bouncing.
- **Persistent-term lookup** — Buffer names are stored in a tuple in
  `:persistent_term` at startup, making hot-path lookups allocation-free.
- **Stream processing** — Each buffer is backed by `SuperCache.Internal.Queue`
  and `SuperCache.Internal.Stream`, which continuously drain the queue and
  push items into the cache.

## Lifecycle

1. `start/1` is called by `SuperCache.Bootstrap` during startup.
2. `enqueue/1` is called by application code via `SuperCache.lazy_put/1`.
3. `stop/0` is called during shutdown to gracefully halt all buffers.

## Examples

    # Start buffers (usually done automatically by Bootstrap)
    SuperCache.Buffer.start(System.schedulers_online())

    # Enqueue data (usually via SuperCache.lazy_put/1)
    SuperCache.Buffer.enqueue({:user, 1, "Alice"})

    # Stop all buffers
    SuperCache.Buffer.stop()

# `buffer_name`

```elixir
@type buffer_name() :: atom()
```

Buffer process name (registered atom).

# `enqueue`

```elixir
@spec enqueue(tuple()) :: :ok | {:error, :not_started}
```

Enqueues `data` into the buffer for the current scheduler.

Uses `:erlang.system_info(:scheduler_id)` to route data to the correct
buffer without random overhead or atom allocation.

If the buffer system has not been started, logs a warning and returns
`{:error, :not_started}`.

## Examples

    SuperCache.Buffer.enqueue({:user, 1, "Alice"})
    # => :ok

# `start`

```elixir
@spec start(pos_integer()) :: :ok
```

Starts one buffer stream per scheduler and registers their names in
`:persistent_term`.

Called automatically by `SuperCache.Bootstrap.start!/1`.

## Examples

    SuperCache.Buffer.start(4)
    # => :ok

# `stop`

```elixir
@spec stop() :: :ok
```

Stops all buffer processes and removes the `:persistent_term` entry.

Called automatically by `SuperCache.Bootstrap.stop/0`.

Sends a `:stop` signal to each buffer queue, which gracefully terminates
the associated stream. Returns `:ok` immediately (fire-and-forget).

## Examples

    SuperCache.Buffer.stop()
    # => :ok

---

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