# `Ussd.Record`
[🔗](https://github.com/spesohq/ussd/blob/main/lib/ussd/record.ex#L1)

Per-session storage, scoped to a `Ussd.Context`'s `uid`/`gid` and backed by a
pluggable `Ussd.Cache`.

Every key is namespaced by the caller's `uid`, unless `public: true` is passed, in
which case it's namespaced by `gid` instead - this is how "continuing" sessions
hand a value from one `uid` (the expired session) to the next (the redial), and how
pagination/truncation counters survive a state being re-entered.

    record = Ussd.Record.new(context.uid, context.gid)
    record |> Ussd.Record.set("otp", "1234", ttl: 300)
    record |> Ussd.Record.get("otp")

# `t`

```elixir
@type t() :: %Ussd.Record{cache: module(), gid: String.t(), uid: String.t()}
```

# `decrement`

```elixir
@spec decrement(t(), String.t(), integer(), keyword()) :: integer()
```

Subtracts `amount` (default 1) from `key`, starting from 0 if unset, and returns the new value.

# `forget`

```elixir
@spec forget(t(), String.t(), keyword()) :: :ok
```

Deletes `key`.

# `forget_many`

```elixir
@spec forget_many(t(), [String.t()], keyword()) :: :ok
```

Deletes several keys at once.

# `get`

```elixir
@spec get(t(), String.t(), term(), keyword()) :: term()
```

Reads `key`, or `default` if it isn't set (or has expired). See `set/4` for `:public`.

# `get_encrypted`

```elixir
@spec get_encrypted(t(), String.t(), term(), keyword()) :: term()
```

Reads and decrypts a value stored with `set_encrypted/4`, or `default` if it isn't set.

# `get_many`

```elixir
@spec get_many(t(), [String.t()], term(), keyword()) :: [term()]
```

Reads several keys at once, in order, each falling back to `default` if unset.

# `has?`

```elixir
@spec has?(t(), String.t(), keyword()) :: boolean()
```

Whether `key` is currently set. Pass `public: true` to check the `gid`-scoped copy instead of the `uid`-scoped one.

# `increment`

```elixir
@spec increment(t(), String.t(), integer(), keyword()) :: integer()
```

Adds `amount` (default 1) to `key`, starting from 0 if unset, and returns the new value.

# `locale`

```elixir
@spec locale(t()) :: String.t() | nil
```

The locale last set for this session via `set_locale/2`, or `nil`.

# `new`

```elixir
@spec new(String.t(), String.t(), module() | nil) :: t()
```

Builds a record scoped to `uid`/`gid`. `cache` overrides `config :ussd, :cache`
(which itself defaults to `Ussd.Cache.ETS`) for just this record.

# `set`

```elixir
@spec set(t(), String.t(), term(), keyword()) :: :ok
```

Stores `value` under `key`.

Options:

  * `:ttl` - seconds until the value expires; `nil` (default) means it never
    expires on its own
  * `:public` - store under `gid` instead of `uid`, so it's visible to a future
    redial under a different `uid` (default `false`)

# `set_encrypted`

```elixir
@spec set_encrypted(t(), String.t(), term(), keyword()) :: :ok
```

Like `set/4`, but encrypts `value` first (AES-256-GCM, keyed by
`config :ussd, :encryption_key`) so it's unreadable at rest - use for PINs,
account numbers, and other sensitive values. Read it back with `get_encrypted/4`,
never with plain `get/4`.

# `set_locale`

```elixir
@spec set_locale(t(), String.t()) :: :ok
```

Persists the caller's chosen locale across requests in this session.

# `set_many`

```elixir
@spec set_many(t(), map() | keyword(), keyword()) :: :ok
```

Like `set/4`, for several `key => value` pairs at once. Same `:ttl`/`:public` options, applied to every key.

---

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