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

Partition resolution and management for SuperCache.

SuperCache splits data across multiple ETS tables (partitions) to reduce
contention and improve parallelism. This module handles:

- **Hashing** — mapping arbitrary terms to partition indices using `:erlang.phash2/2`.
- **Resolution** — translating partition indices to ETS table atoms.
- **Lifecycle** — initialising and tearing down the partition registry.

## How partitioning works

1. A term (usually extracted from a tuple via `:partition_pos`) is hashed
   with `:erlang.phash2/2` modulo the number of partitions.
2. The resulting index is looked up in `SuperCache.Partition.Holder` to
   get the corresponding ETS table atom.
3. All reads and writes for that term go to that table.

## Example

    # Start with 4 partitions
    SuperCache.Partition.start(4)

    # Resolve partition for a term
    SuperCache.Partition.get_partition(:user_123)
    # => :"SuperCache.Storage.Ets_2"

    # Get partition index directly
    SuperCache.Partition.get_partition_order(:user_123)
    # => 2

    # Clean up
    SuperCache.Partition.stop()

# `get_all_partition`

```elixir
@spec get_all_partition() :: [atom()]
```

List all registered partition ETS table atoms.

Returns a flat list of table names, excluding internal registry entries.

## Examples

    SuperCache.Partition.start(3)
    SuperCache.Partition.get_all_partition()
    # => [:"SuperCache.Storage.Ets_0", :"SuperCache.Storage.Ets_1", :"SuperCache.Storage.Ets_2"]

# `get_num_partition`

```elixir
@spec get_num_partition() :: pos_integer()
```

Return the configured number of partitions.

Reads directly from the `Holder` ETS table — no GenServer hop.
Raises if the partition count has not been initialised.

## Examples

    SuperCache.Partition.start(8)
    SuperCache.Partition.get_num_partition()
    # => 8

# `get_partition`

```elixir
@spec get_partition(any()) :: atom()
```

Resolve the ETS table atom for a given term.

The term is hashed to derive a partition index, which is then looked up
in the `Holder` registry to return the corresponding ETS table name.

This is the primary entry point used by the public API when the caller
has a raw key or partition value.

## Examples

    SuperCache.Partition.get_partition(:session_abc)
    # => :"SuperCache.Storage.Ets_1"

    SuperCache.Partition.get_partition({:user, 42})
    # => :"SuperCache.Storage.Ets_3"

# `get_partition_by_idx`

```elixir
@spec get_partition_by_idx(non_neg_integer()) :: atom() | nil
```

Resolve the ETS table atom directly from a partition index.

Does **not** re-hash the input. Safe to call from the Replicator and
Router where the index is already known.

## Examples

    SuperCache.Partition.get_partition_by_idx(0)
    # => :"SuperCache.Storage.Ets_0"

# `get_partition_order`

```elixir
@spec get_partition_order(any()) :: non_neg_integer()
@spec get_partition_order(any()) :: non_neg_integer()
```

Compute the partition index for any term.

Uses `:erlang.phash2/2` with the configured number of partitions as the
range. The result is an integer in `0..(num_partitions - 1)`.

## Examples

    SuperCache.Partition.get_partition_order(:hello)
    # => 2

# `get_partition_order_from_data`

```elixir
@spec get_partition_order_from_data(tuple()) :: non_neg_integer()
```

Compute the partition index for a data tuple using the configured `:partition_pos`.

Extracts the element at `:partition_pos` from the tuple, then hashes it
to determine the partition index.

## Examples

    SuperCache.Config.set_config(:partition_pos, 1)
    SuperCache.Partition.get_partition_order_from_data({:user, 42, "data"})
    # => (hash of 42) mod num_partitions

# `get_schedulers`

```elixir
@spec get_schedulers() :: pos_integer()
```

Return the number of online schedulers in the Erlang VM.

Used as the default partition count when `:num_partition` is not
explicitly configured.

## Examples

    SuperCache.Partition.get_schedulers()
    # => 8  (on an 8-core machine)

# `start`

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

Initialise the partition registry.

Stores the total partition count and registers each index (0 to N-1)
with its corresponding ETS table name.

Called by `SuperCache.Bootstrap` during startup.

## Examples

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

# `stop`

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

Clear all partition registrations from the registry.

Does **not** delete the ETS tables themselves — only removes the
index-to-name mappings from the `Holder`.

Called by `SuperCache.Bootstrap` during shutdown.

---

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