SuperCache.Cluster.DistributedHelpers (SuperCache v1.3.0)

Copy Markdown View Source

Shared helpers for distributed read/write operations.

Extracts common patterns used across SuperCache.KeyValue, SuperCache.Queue, SuperCache.Stack, and SuperCache.Struct for:

Quorum reads

Quorum reads use Task.async with early termination — as soon as a majority of replicas agree on a result, remaining tasks are killed. This is more efficient than Task.async_stream which always waits for all tasks to complete before computing consensus.

Summary

Functions

Applies a batch of write operations with the configured replication strategy.

Returns true when the cluster is running in distributed mode.

Returns true if the current node holds a replica (primary or secondary) for the given partition index.

Reads from the primary replica for the given partition.

Reads from all replicas and returns the result that achieves quorum (majority).

Routes a read operation according to the requested read mode.

Routes a write operation to the primary replica for the given partition.

Functions

apply_write(idx, partition, ops)

@spec apply_write(non_neg_integer(), term(),
  put: term(),
  delete: term(),
  delete_match: term(),
  delete_all: term()
) :: :ok | {:error, term()}

Applies a batch of write operations with the configured replication strategy.

  • Strong replication (:strong): delegates to ThreePhaseCommit.commit/2 for atomic distributed commits via the WAL-based 3PC protocol.
  • Async / sync replication: applies each operation to local storage first, then replicates to replica nodes via Replicator.

Operations

Each operation is a tuple:

OperationDescription
{:put, record}Insert or update a record
{:delete, key}Delete a record by key
{:delete_match, pattern}Delete records matching a pattern
{:delete_all, _}Delete all records in the partition

Returns

  • :ok on success
  • {:error, reason} when 3PC commit fails (strong mode only)

distributed?()

@spec distributed?() :: boolean()

Returns true when the cluster is running in distributed mode.

Inlined by the compiler for hot-path performance.

has_partition?(partition_idx)

@spec has_partition?(non_neg_integer()) :: boolean()

Returns true if the current node holds a replica (primary or secondary) for the given partition index.

read_primary(caller, fun, args, partition_idx)

@spec read_primary(module(), atom(), [term()], non_neg_integer()) :: term()

Reads from the primary replica for the given partition.

If the current node is the primary, the function is applied locally. Otherwise, an :erpc.call is made to the primary node.

read_quorum(caller, fun, args, partition_idx)

@spec read_quorum(module(), atom(), [term()], non_neg_integer()) :: term()

Reads from all replicas and returns the result that achieves quorum (majority).

Uses Task.async with early termination: as soon as a majority of replicas agree on a result, remaining tasks are killed immediately. This avoids waiting for slow replicas once quorum is satisfied.

If no result reaches quorum, falls back to the primary node's result.

route_read(caller, fun, args, partition_idx, opts)

@spec route_read(module(), atom(), [term()], non_neg_integer(), keyword()) :: term()

Routes a read operation according to the requested read mode.

Read modes

  • :local — read from the local node. If the local node does not hold a replica, automatically escalates to :primary.
  • :primary — read from the primary replica.
  • :quorum — read from all replicas and return the majority result.

Parameters

  • caller — the module that owns the function being called
  • fun — the function name (atom)
  • args — the function arguments (list)
  • partition_idx — the partition index
  • opts — keyword list, supports :read_mode (default :local)

Returns

The return value of the called function.

route_write(caller, fun, args, partition_idx)

@spec route_write(module(), atom(), [term()], non_neg_integer()) :: term()

Routes a write operation to the primary replica for the given partition.

If the current node is the primary, the function is applied locally. Otherwise, an :erpc.call is made to the primary node.

Parameters

  • caller — the module that owns the function being called (replaces __MODULE__)
  • fun — the function name (atom)
  • args — the function arguments (list)
  • partition_idx — the partition index used to look up the primary node

Returns

The return value of the called function, or raises on :erpc failure.