Packages
An in-memory caching library using tuples as the core data type, with support for structs, key/value pairs, queues, and stacks. Includes experimental distributed caching.
Current section
Files
Jump to
Current section
Files
lib/bootstrap.ex
defmodule SuperCache.Bootstrap do
@moduledoc """
Unified startup and shutdown for SuperCache.
Handles both `:local` (single-node) and `:distributed` (cluster) modes.
The mode is selected via the `:cluster` option:
- `:local` (default) — single-node ETS cache, no replication.
- `:distributed` — cluster-aware; delegates to `SuperCache.Cluster.Bootstrap`.
## Options
| Option | Type | Default | Description |
|---------------------|---------|-----------------|--------------------------------------|
| `:key_pos` | integer | `0` | Tuple index used as the ETS key |
| `:partition_pos` | integer | `0` | Tuple index used to select partition |
| `:cluster` | atom | `:local` | `:local` or `:distributed` |
| `:num_partition` | integer | scheduler count | Number of ETS partitions |
| `:table_type` | atom | `:set` | ETS table type |
| `:table_prefix` | string | `"SuperCache…"` | Prefix for ETS table atom names |
Additional options for `:distributed` mode (see `SuperCache.Cluster.Bootstrap`):
| Option | Type | Default | Description |
|----------------------|---------|----------|------------------------------------|
| `:replication_factor`| integer | `2` | Total copies (primary + replicas) |
| `:replication_mode` | atom | `:async` | `:async`, `:sync`, or `:strong` |
"""
require Logger
alias SuperCache.{Config, Partition, Storage, Buffer}
@default_opts [key_pos: 0, partition_pos: 0, cluster: :local, table_type: :set]
@valid_table_types [:set, :ordered_set, :bag, :duplicate_bag]
@doc "Start SuperCache with default options (local mode)."
@spec start!() :: :ok
def start!(), do: start!(@default_opts)
@doc "Start SuperCache with the given keyword options. Raises on invalid config."
@spec start!(keyword) :: :ok
def start!(opts) do
Logger.info("super_cache, bootstrap, starting with opts: #{inspect(opts)}")
validate!(opts)
case Keyword.get(opts, :cluster, :local) do
:distributed -> SuperCache.Cluster.Bootstrap.start!(opts)
:local -> local_start!(opts)
end
end
@doc "Stop SuperCache and release all ETS resources."
@spec stop() :: :ok
def stop() do
case Config.get_config(:cluster, :local) do
:distributed -> SuperCache.Cluster.Bootstrap.stop()
:local -> local_stop()
end
end
# ── Private — local-mode lifecycle ───────────────────────────────────────────
defp local_start!(opts) do
Config.clear_config()
Enum.each(opts, fn {k, v} -> Config.set_config(k, v) end)
num = resolve_num_partition()
resolve_table_type()
resolve_table_prefix()
Partition.start(num)
Storage.start(num)
Buffer.start(Partition.get_schedulers())
Config.set_config(:started, true)
Logger.info("super_cache, bootstrap, ready in local mode (#{num} partitions)")
:ok
end
defp local_stop() do
Buffer.stop()
case Config.get_config(:num_partition) do
nil -> :ok
n -> Storage.stop(n)
end
Partition.stop()
Config.set_config(:started, false)
:ok
end
# ── Private — validation ─────────────────────────────────────────────────────
defp validate!(opts) do
unless Keyword.keyword?(opts),
do: raise(ArgumentError, "options must be a keyword list, got: #{inspect(opts)}")
for key <- [:key_pos, :partition_pos] do
unless Keyword.has_key?(opts, key),
do: raise(ArgumentError, "missing required option: #{inspect(key)}")
end
end
# ── Private — config resolution ──────────────────────────────────────────────
defp resolve_num_partition() do
case Config.get_config(:num_partition, :not_found) do
:not_found -> n = Partition.get_schedulers(); Config.set_config(:num_partition, n); n
n -> n
end
end
defp resolve_table_type() do
case Config.get_config(:table_type, :not_found) do
:not_found -> Config.set_config(:table_type, :set)
t when t in @valid_table_types -> :ok
bad -> raise ArgumentError, "unsupported table type: #{inspect(bad)}, must be one of #{inspect(@valid_table_types)}"
end
end
defp resolve_table_prefix() do
case Config.get_config(:table_prefix, :not_found) do
:not_found -> Config.set_config(:table_prefix, "SuperCache.Storage.Ets")
_ -> :ok
end
end
end