{"id":20057644,"url":"https://github.com/todesking/sharrrd","last_synced_at":"2025-07-03T12:03:46.973Z","repository":{"id":136156376,"uuid":"25426143","full_name":"todesking/sharrrd","owner":"todesking","description":"Consistent hashing for Scala.","archived":false,"fork":false,"pushed_at":"2014-10-22T13:49:55.000Z","size":200,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-02T09:45:01.172Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/todesking.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-19T12:22:01.000Z","updated_at":"2019-11-26T01:16:38.000Z","dependencies_parsed_at":"2023-03-12T17:11:27.895Z","dependency_job_id":null,"html_url":"https://github.com/todesking/sharrrd","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/todesking/sharrrd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todesking%2Fsharrrd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todesking%2Fsharrrd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todesking%2Fsharrrd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todesking%2Fsharrrd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/todesking","download_url":"https://codeload.github.com/todesking/sharrrd/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todesking%2Fsharrrd/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263322786,"owners_count":23448712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T12:59:46.907Z","updated_at":"2025-07-03T12:03:46.948Z","avatar_url":"https://github.com/todesking.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sharrrd: Consistent Hashing for Scala\n\n## Basic architecture\n\n```\nKey =(hash algorithm)=\u003e Hash code ===(hash to node mapping)==\u003e Real node\n                                  ~HashRing[HashT, RealNodeT]~\n                                  ~~~~(                  )~~~~\n                                  ~~~~(previous hash ring)~~~~\n                                  ~~~~(                  )~~~~\n    ~~~~~~~~~~~~~~~~ Sharding[KeyT, HashT, RealNodeT] ~~~~~~~~\n```\n\nYou can customize hash and mapping algorithm. Default implementation available at `DefaultHashRing`.\n\n## Simple example for default implementation\n\n```scala\nimport com.todesking.sharrrd\n\nval redisInstances = getRedisInstances()\nval randomSeed = 0L\n\nval assignmentPolicy = new DefaultAssignmentPolicy(\n  assignPerNode = 100,\n  RandomSource.fromJavaRandomInt(new java.util.Random(randomSeed))\n)\n\n// Sharding that key = String, hash = Int, node = RedisInstance\nval sharding = new Sharding[String, Int, RedisInstance](\n  key =\u003e myHashFunction(key),\n  new DefaultHashRing(assignmentpolicy).add(redisInstances:_*),\n  Seq() // recent hash ring definitions(newer first)\n)\n\ndef put(key:String, value:Int):Unit = {\n  val redis = sharding.realNodeOf(key)\n  redis.put(key, value)\n\n  // or\n  sharding.operate(key) { redis =\u003e redis.put(key, value) }\n}\n\n// Read data from redis. Dig down recent 10 hash ring histories.\ndef get(key:String):Option[Int] = {\n  sharding.operateUntil(key, 10) { (hashRing, redis) =\u003e redis.getOption(key) }\n}\n```\n\n\n## Interface\n\n```scala\nclass Sharding[KeyT, HashT, RealNodeT] {\n  val currentHashRing:HashRing[HashT, RealNodeT]\n  val oldHashRings:Seq[HashRing[HashT, RealNodeT]] // sequence of old rings(newer first)\n\n  def realNodeOf(key:KeyT):RealNodeT\n  def operate[A](key:KeyT)(f:(RealNodeT) =\u003e A):A\n  def operateUntil[A](key:KeyT, maxHistoryDepth:Int)(f:(HashRing[HashT, RealNodeT], RealNodeT) =\u003e Option[A]):Option[A]\n}\n\ntrait HashRing[HashT, RealNodeT] {\n  def realNodeOf(hash:HashT):RealNodeT\n}\n\ntrait FlexibleHashRing[HashT, RealNodeT, SelfT \u003c: HashRing[HashT, RealNodeT]] extends HashRing[HashT, RealNodeT] {\n  def add(nodes:RealNodeT*):SelfT\n  def remove(nodes:RealNodeT*):SelfT\n}\n\ntrait AssignmentPolicy[HashT, RealNodeT] {\n  trait Assigner {\n    def assign(assigned:Set[HashT], node:RealNodeT):Seq[HashT]\n    def snapshot():AssignmentPolicy[HashT, RealNodeT]\n  }\n  def newAssigner():Assigner\n}\n\nclass DefaultAssignmentPolicy[HashT, RealNodeT](assignPerNode:Int, rand:RandomSource[HashT]) extends AssignmentPolicy[HashT, RealNodeT]\n\nclass DefaultHashRing[HashT, RealNodeT](\n  val table:SortedMap[HashT, RealNodeT],\n  val assignmentPolicy:AssignmentPolicy[HashT, RealNodeT]\n) extends FlexibleHashRing[HashT, RealNodeT, DefaultHashRing[HashT, RealNodeT]] {\n  def this(assignmentPolicy:AssignmentPolicy[HashT, RealNodeT])(implicit ev:Ordering[HashT])\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodesking%2Fsharrrd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftodesking%2Fsharrrd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodesking%2Fsharrrd/lists"}