# `Lotus.Cache`
[🔗](https://github.com/elixir-lotus/lotus/blob/v1.3.0/lib/lotus/cache.ex#L1)

Lotus cache facade. If no adapter configured, acts as a no-op pass-through.

# `key`

```elixir
@type key() :: binary()
```

# `opts`

```elixir
@type opts() :: Keyword.t()
```

# `ttl_ms`

```elixir
@type ttl_ms() :: non_neg_integer()
```

# `value`

```elixir
@type value() :: any()
```

# `build_options`

```elixir
@spec build_options(term(), [String.t()]) :: opts()
```

Builds the per-entry options for a cache write.

Layers the caller's `:cache` option over the entry options set in
application config, then adds the invalidation tags. A caller that passes
no `:cache` option, or an atom such as `:bypass`, still gets the
configured defaults.

# `delete`

```elixir
@spec delete(key()) :: :ok | {:error, term()}
```

Removes one entry.

When the adapter's delete is node-local the call is relayed to the other
nodes of the cluster. See `scope/1`.

# `enabled?`

```elixir
@spec enabled?() :: boolean()
```

# `get`

```elixir
@spec get(key()) :: {:ok, value()} | :miss
```

# `get_or_store`

```elixir
@spec get_or_store(key(), ttl_ms(), (-&gt; value()), opts()) ::
  {:ok, value(), :hit | :miss | atom()} | {:error, term()}
```

# `invalidate_scope`

```elixir
@spec invalidate_scope(term()) :: :ok | {:error, term()}
```

Invalidates all cache entries associated with the given scope.

Uses tag-based invalidation — each scoped cache entry is tagged with
`"scope:<digest>"`, so this clears only entries for the specified scope
without flushing the entire source cache.

## Examples

    Lotus.Cache.invalidate_scope(%{tenant_id: 42})
    Lotus.Cache.invalidate_scope(%{role: :admin})

# `invalidate_tags`

```elixir
@spec invalidate_tags([binary()]) :: :ok | {:error, term()}
```

Invalidates every entry that carries one of `tags`.

When the adapter's tag bookkeeping is node-local the call is relayed to
the other nodes of the cluster. See `scope/1`.

# `put`

```elixir
@spec put(key(), value(), ttl_ms(), opts()) :: :ok | {:error, term()}
```

# `scope`

```elixir
@spec scope(Lotus.Cache.Adapter.relayed_operation()) :: :node | :cluster
```

How far one `delete/1` or `invalidate_tags/1` on the configured adapter
reaches.

`:node` means the call only touches the calling node, so it is relayed
to the other nodes over `Lotus.Notifier` and applied there by
`Lotus.Cache.Relay`. `:cluster` means one call already reaches every
node and nothing is relayed. An adapter that does not implement
`c:Lotus.Cache.Adapter.scope/1` counts as `:node` for both. Without a
configured adapter the answer is `:cluster`, because there is nothing
to relay.

---

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