# `Tink.Cache`
[🔗](https://github.com/iamkanishka/tink.ex/blob/v0.1.1/lib/tink/cache.ex#L1)

Caching layer for Tink API responses.

This module provides intelligent caching for API responses to reduce API calls,
improve performance, and stay within rate limits. It uses Cachex for persistent
caching with configurable TTLs.

## Configuration

    config :tink, :cache,
      enabled: true,
      default_ttl: :timer.minutes(5),
      max_size: 1000

## Cache TTLs by Resource Type

- **Providers**: 1 hour (rarely change)
- **Categories**: 1 day (static reference data)
- **User Data / Accounts**: 5 minutes
- **Balances**: 1 minute (frequently updated)
- **Statistics**: 1 hour (aggregated data)
- **Credentials**: 30 seconds (status changes frequently)
- **Reports** (income/expense/risk): 24 hours (immutable once generated)

# `build_key`

```elixir
@spec build_key([String.t() | atom()]) :: String.t()
```

Builds a cache key from a list of components joined by `:`.

    "providers:GB" = Tink.Cache.build_key(["providers", "GB"])

# `clear`

```elixir
@spec clear() :: :ok | {:error, integer()}
```

Clears all cached values.

# `delete`

```elixir
@spec delete(String.t()) :: :ok | {:error, boolean()}
```

Deletes a value from the cache.

# `enabled?`

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

Checks if caching is enabled.

# `fetch`

```elixir
@spec fetch(String.t(), (-&gt; {:ok, term()} | {:error, term()}), keyword()) ::
  {:ok, term()} | {:error, term()}
```

Fetches a value from cache, computing it with `fun` on miss.

    {:ok, providers} = Tink.Cache.fetch("providers:GB", fn ->
      call_api()
    end, resource_type: :providers)

# `get`

```elixir
@spec get(String.t()) :: {:ok, term()} | {:error, term()}
```

Gets a value from the cache.

Returns `{:ok, value}` on hit, `{:error, :not_found}` on miss.

# `invalidate_user`

```elixir
@spec invalidate_user(String.t()) :: :ok
```

Invalidates all cache entries belonging to a user.

Uses a `Stream` over Cachex keys to avoid loading all keys into memory at
once, making it efficient even for large caches.

All user keys are stored under the `"<user_id>:"` prefix, so prefix matching
is exact and cannot collide with a shorter user ID like `"user_1"` matching
`"user_10:..."`.

# `put`

```elixir
@spec put(String.t(), term(), keyword()) :: :ok | {:error, term()}
```

Puts a value in the cache with optional TTL or resource type.

    :ok = Tink.Cache.put("providers:GB", providers, resource_type: :providers)
    :ok = Tink.Cache.put("custom:key", value, ttl: :timer.minutes(10))

# `stats`

```elixir
@spec stats() ::
  %{hit_rate: float(), hits: term(), misses: term(), size: term()} | nil
```

Returns cache statistics, or `nil` if cache is disabled.

    %{hit_rate: 0.75, hits: 150, misses: 50, size: 45} = Tink.Cache.stats()

---

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