## Sharding — hash-based and range-based data distribution import std/tables import std/hashes import std/algorithm import std/sets type ShardStrategy* = enum ssHash = "hash" ssRange = "range" ssConsistent = "consistent" Shard* = object id*: int name*: string minKey*: string maxKey*: string nodeIds*: seq[string] # replica node ids isActive*: bool entryCount*: int ShardRouter* = ref object strategy*: ShardStrategy shards*: seq[Shard] vnodeRing*: seq[(uint64, int)] # (hash, shard_id) sorted replicas*: int ShardConfig* = object numShards*: int replicas*: int strategy*: ShardStrategy proc defaultShardConfig*(): ShardConfig = ShardConfig(numShards: 4, replicas: 1, strategy: ssHash) proc newShardRouter*(config: ShardConfig = defaultShardConfig()): ShardRouter = result = ShardRouter( strategy: config.strategy, shards: @[], vnodeRing: @[], replicas: config.replicas, ) for i in 0..= shard.minKey and key <= shard.maxKey: return i return 0 proc getShardConsistent*(router: ShardRouter, key: string): int = if router.vnodeRing.len == 0: return getShardHash(router, key) let h = hashKey(key) for (ringHash, shardId) in router.vnodeRing: if h <= ringHash: return shardId return router.vnodeRing[0][1] proc getShard*(router: ShardRouter, key: string): int = case router.strategy of ssHash: router.getShardHash(key) of ssRange: router.getShardRange(key) of ssConsistent: router.getShardConsistent(key) proc addVirtualNodes*(router: var ShardRouter, numVnodes: int = 100) = for shard in router.shards: for i in 0..