Class PartitionRouter

java.lang.Object
com.loomcache.server.sharding.PartitionRouter

public class PartitionRouter extends Object
Routes keys to the correct Raft group based on partition assignment.

Routing pipeline: hash(key) -> partition -> raftGroup -> leader node

Uses MurmurHash3 for consistent, well-distributed key hashing across 271 partitions (prime number for better distribution). Partitions are then mapped to Raft groups, each running an independent consensus instance.

Thread Safety: Partition assignments are updated atomically under a write lock. All read operations use a read lock for concurrent access. The volatile partitionToGroup array reference provides an additional fast-path for snapshot reads.

Failure Handling: When a Raft group leader is unavailable, callers should retry after a leader election completes. The router itself does not block on leader availability.

Since:
2.0
  • Field Details

    • DEFAULT_NUM_PARTITIONS

      public static final int DEFAULT_NUM_PARTITIONS
      Default number of partitions (271 -- prime for better distribution).
      See Also:
  • Constructor Details

    • PartitionRouter

      public PartitionRouter(RaftGroupManagerApi raftGroupManager)
      Creates a router with the default partition count (271) and a single Raft group.
      Parameters:
      raftGroupManager - the Raft group manager for group lookups (must not be null)
    • PartitionRouter

      public PartitionRouter(int numPartitions, RaftGroupManagerApi raftGroupManager)
      Creates a router with the specified partition count and a single Raft group.

      All partitions are initially assigned to group 0. Call rebalance(int) to redistribute across multiple groups.

      Parameters:
      numPartitions - the number of partitions (must be > 0)
      raftGroupManager - the Raft group manager (must not be null)
    • PartitionRouter

      public PartitionRouter(int numPartitions, RaftGroupManagerApi raftGroupManager, PartitioningStrategy<Object> partitioningStrategy)
      Creates a router with the specified partition count, Raft manager, and partitioning strategy.
      Parameters:
      numPartitions - the number of partitions (must be > 0)
      raftGroupManager - the Raft group manager (must not be null)
      partitioningStrategy - fallback strategy for non-PartitionAware keys (must not be null)
  • Method Details

    • getPartition

      public int getPartition(String key)
      Computes the partition ID for a given key using MurmurHash3.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the partition ID (0 to numPartitions-1)
    • getPartition

      public int getPartition(Object key)
      Computes the partition ID for a key object, honoring PartitionAware keys.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the partition ID (0 to numPartitions-1)
    • getRaftGroup

      public int getRaftGroup(String key)
      Determines which Raft group owns the given key.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the Raft group ID that owns this key's partition
    • getRaftGroup

      public int getRaftGroup(Object key)
      Determines which Raft group owns the given key object.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the Raft group ID that owns this key's partition
    • getRaftGroupForPartition

      public int getRaftGroupForPartition(int partitionId)
      Returns the Raft group ID that owns the specified partition.
      Parameters:
      partitionId - the partition ID (0 to numPartitions-1)
      Returns:
      the Raft group ID owning this partition
    • getWriteOwnerForPartition

      public int getWriteOwnerForPartition(int partitionId)
      Returns the group that should currently receive writes for the specified partition.

      During migration this may temporarily differ from the committed routing table while source-side writes are redirected before cleanup completes.

      Parameters:
      partitionId - the partition ID (0 to numPartitions-1)
      Returns:
      the write owner group for this partition
    • getRaftNodeForKey

      public RaftNodeApi getRaftNodeForKey(String key)
      Returns the RaftNode for the group that owns the given key.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the RaftNode for the owning group (never null)
    • getRaftNodeForKey

      public RaftNodeApi getRaftNodeForKey(Object key)
      Returns the RaftNode for the group that owns the given key object.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the RaftNode for the owning group (never null)
    • getLeaderForKey

      public @Nullable String getLeaderForKey(String key)
      Returns the leader node ID for the Raft group that owns the given key.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the leader node ID, or null if no leader is currently elected
    • getLeaderForKey

      public @Nullable String getLeaderForKey(Object key)
      Returns the leader node ID for the Raft group that owns the given key object.
      Parameters:
      key - the key to route (must not be null)
      Returns:
      the leader node ID, or null if no leader is currently elected
    • rebalance

      public void rebalance(int numGroups)
      Rebalances partitions evenly across the specified number of Raft groups.

      Uses round-robin assignment: partition i is assigned to group i % numGroups. This ensures even distribution with at most 1 partition difference between any two groups.

      Parameters:
      numGroups - the target number of Raft groups (must be > 0)
    • applyMapping

      public void applyMapping(int[] mapping)
      Applies a specific partition-to-group mapping.

      Used during migration to set precise partition ownership rather than the default round-robin distribution.

      Parameters:
      mapping - the new mapping array (length must equal numPartitions)
    • getRevision

      public long getRevision()
      Monotonic rebalance revision — increments on every rebalance(int) and applyMapping(int[]), and is preserved or advanced on snapshot restore. Clients polling the partition table use this to reject stale out-of-order refresh responses.
      Returns:
      the current revision (never decreases across the lifetime of this router)
      Since:
      2.1
    • toSnapshot

      public HashMap<String,Object> toSnapshot()
      Creates a serializable snapshot of the partition-to-group mapping.

      The mapping array is cloned under the read lock to capture a consistent point-in-time view. This allows the partition layout to survive node crashes via the Raft snapshot system.

      Returns:
      a HashMap containing the partition count and mapping array
    • restoreFromSnapshot

      public void restoreFromSnapshot(HashMap<String,Object> snapshot)
      Restores the partition-to-group mapping from a Raft snapshot.

      If the mapping length matches the configured partition count, it is applied atomically with the persisted revision. Missing or malformed mappings fail closed so data structures are not restored under an unrelated/default routing layout.

      Parameters:
      snapshot - the snapshot data previously produced by toSnapshot()
    • getAssignment

      public PartitionAssignment getAssignment()
      Returns an immutable snapshot of the current partition assignment.
      Returns:
      the current assignment (never null)