{"id":13481475,"url":"https://github.com/etaty/rediscala","last_synced_at":"2025-03-27T12:30:52.502Z","repository":{"id":1019414,"uuid":"9449740","full_name":"etaty/rediscala","owner":"etaty","description":"Non-blocking, Reactive Redis driver for Scala (with Sentinel support)","archived":false,"fork":false,"pushed_at":"2024-05-07T19:31:37.000Z","size":4725,"stargazers_count":789,"open_issues_count":86,"forks_count":142,"subscribers_count":40,"default_branch":"master","last_synced_at":"2024-10-30T15:50:48.385Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/etaty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-15T13:49:16.000Z","updated_at":"2024-10-27T14:24:00.000Z","dependencies_parsed_at":"2024-10-30T15:41:55.655Z","dependency_job_id":null,"html_url":"https://github.com/etaty/rediscala","commit_stats":{"total_commits":353,"total_committers":33,"mean_commits":"10.696969696969697","dds":0.5750708215297451,"last_synced_commit":"5600b0023c44fea410afe6c7d2d89b6ec26a0533"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/etaty%2Frediscala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/etaty%2Frediscala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/etaty%2Frediscala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/etaty%2Frediscala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/etaty","download_url":"https://codeload.github.com/etaty/rediscala/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245844837,"owners_count":20681786,"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-07-31T17:00:52.165Z","updated_at":"2025-03-27T12:30:52.099Z","avatar_url":"https://github.com/etaty.png","language":"Scala","funding_links":[],"categories":["Database","Table of Contents"],"sub_categories":["Database"],"readme":"rediscala [![Build Status](https://travis-ci.org/etaty/rediscala.svg)](https://travis-ci.org/etaty/rediscala) [![Coverage Status](https://img.shields.io/coveralls/etaty/rediscala.svg)](https://coveralls.io/r/etaty/rediscala?branch=master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.etaty/rediscala_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.etaty/rediscala_2.12)\n=========\n\nA [Redis](http://redis.io/) client for Scala with non-blocking and asynchronous I/O operations.\n\n * Reactive : Redis requests/replies are wrapped in Futures.\n\n * Typesafe : Redis types are mapped to Scala types.\n\n * Fast : Rediscala uses redis pipelining. Blocking redis commands are moved into their own connection. \nA worker actor handles I/O operations (I/O bounds), another handles decoding of Redis replies (CPU bounds).\n\n### Set up your project dependencies\n\nIf you use SBT, you just have to edit `build.sbt` and add the following:\n\nFrom version 1.9.0: \n * use akka 2.5.23 (java 1.8)\n * released for scala\n   * 2.11\n   * 2.12\n   * 2.13\n```scala\nlibraryDependencies += \"com.github.etaty\" %% \"rediscala\" % \"1.9.0\"\n```\n\nFrom version 1.8.0: \n * use akka 2.4.12 (java 1.8)\n * released for scala 2.11 \u0026 2.12\n```scala\nlibraryDependencies += \"com.github.etaty\" %% \"rediscala\" % \"1.8.0\"\n```\n\nFrom version 1.3.1: \n * use akka 2.3\n * released for scala 2.10 \u0026 2.11\n```scala\n// new repo on maven.org\nlibraryDependencies += \"com.github.etaty\" %% \"rediscala\" % \"1.7.0\"\n\n\n// old repo on bintray (1.5.0 and inferior version)\nresolvers += \"rediscala\" at \"http://dl.bintray.com/etaty/maven\"\nlibraryDependencies += \"com.etaty.rediscala\" %% \"rediscala\" % \"1.5.0\"\n```\n\nFor older rediscala versions (\u003c= 1.3):\n * use akka 2.2\n * released for scala 2.10 only\n * use github \"repo\"\n```scala\nresolvers += \"rediscala\" at \"https://raw.github.com/etaty/rediscala-mvn/master/releases/\"\n\nlibraryDependencies += \"com.etaty.rediscala\" %% \"rediscala\" % \"1.3\"\n```\n\n### Connect to the database\n\n```scala\nimport redis.RedisClient\nimport scala.concurrent.Await\nimport scala.concurrent.duration._\nimport scala.concurrent.ExecutionContext.Implicits.global\n\nobject Main extends App {\n  implicit val akkaSystem = akka.actor.ActorSystem()\n\n  val redis = RedisClient()\n\n  val futurePong = redis.ping()\n  println(\"Ping sent!\")\n  futurePong.map(pong =\u003e {\n    println(s\"Redis replied with a $pong\")\n  })\n  Await.result(futurePong, 5 seconds)\n\n  akkaSystem.shutdown()\n}\n```\n\n### Basic Example\n\nhttps://github.com/etaty/rediscala-demo\n\nYou can fork with : `git clone git@github.com:etaty/rediscala-demo.git` then run it, with `sbt run`\n\n\n### Redis Commands\n\nAll commands are supported :\n* [Keys](http://redis.io/commands#generic) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Keys))\n* [Strings](http://redis.io/commands#string) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Strings))\n* [Hashes](http://redis.io/commands#hash) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Hashes))\n* [Lists](http://redis.io/commands#list) \n  * non-blocking ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Lists))\n  * blocking ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.BLists))\n* [Sets](http://redis.io/commands#set) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Sets))\n* [Sorted Sets](http://redis.io/commands#sorted_set) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.SortedSets))\n* [Pub/Sub](http://redis.io/commands#pubsub) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Publish))\n* [Transactions](http://redis.io/commands#transactions) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Transactions))\n* [Connection](http://redis.io/commands#connection) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Connection))\n* [Scripting](http://redis.io/commands#scripting) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Scripting))\n* [Server](http://redis.io/commands#server) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.Server))\n* [HyperLogLog](http://redis.io/commands#hyperloglog) ([scaladoc](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.HyperLogLog))\n\n### Blocking commands\n\n[RedisBlockingClient](http://etaty.github.io/rediscala/latest/api/index.html#redis.RedisBlockingClient) is the instance allowing access to blocking commands :\n* blpop\n* brpop\n* brpopplush\n\n```scala\n  redisBlocking.blpop(Seq(\"workList\", \"otherKeyWithWork\"), 5 seconds).map(result =\u003e {\n    result.map({\n      case (key, work) =\u003e println(s\"list $key has work : ${work.utf8String}\")\n    })\n  })\n```\nFull example: [ExampleRediscalaBlocking](https://github.com/etaty/rediscala-demo/blob/master/src/main/scala/ExampleRediscalaBlocking.scala)\n\nYou can fork with: `git clone git@github.com:etaty/rediscala-demo.git` then run it, with `sbt run`\n\n\n### Transactions\n\nThe idea behind transactions in Rediscala is to start a transaction outside of a redis connection.\nWe use the [TransactionBuilder](http://etaty.github.io/rediscala/latest/api/index.html#redis.commands.TransactionBuilder) to store call to redis commands (and for each command we give back a future).\nWhen `exec` is called, `TransactionBuilder` will build and send all the commands together to the server. Then the futures will be completed.\nBy doing that we can use a normal connection with pipelining, and avoiding to trap a command from outside, in the transaction...\n\n```scala\n  val redisTransaction = redis.transaction() // new TransactionBuilder\n  redisTransaction.watch(\"key\")\n  val set = redisTransaction.set(\"key\", \"abcValue\")\n  val decr = redisTransaction.decr(\"key\")\n  val get = redisTransaction.get(\"key\")\n  redisTransaction.exec()\n```\n\nFull example: [ExampleTransaction](https://github.com/etaty/rediscala-demo/blob/master/src/main/scala/ExampleTransaction.scala)\n\nYou can fork with : `git clone git@github.com:etaty/rediscala-demo.git` then run it, with `sbt run`\n\n[TransactionsSpec](https://github.com/etaty/rediscala/blob/master/src/test/scala/redis/commands/TransactionsSpec.scala) will reveal even more gems of the API.\n\n### Pub/Sub\n\nYou can use a case class with callbacks [RedisPubSub](http://etaty.github.io/rediscala/latest/api/index.html#redis.RedisPubSub)\nor extend the actor [RedisSubscriberActor](http://etaty.github.io/rediscala/latest/api/index.html#redis.actors.RedisSubscriberActor) as shown in the example below\n\n```scala\nobject ExamplePubSub extends App {\n  implicit val akkaSystem = akka.actor.ActorSystem()\n\n  val redis = RedisClient()\n\n  // publish after 2 seconds every 2 or 5 seconds\n  akkaSystem.scheduler.schedule(2 seconds, 2 seconds)(redis.publish(\"time\", System.currentTimeMillis()))\n  akkaSystem.scheduler.schedule(2 seconds, 5 seconds)(redis.publish(\"pattern.match\", \"pattern value\"))\n  // shutdown Akka in 20 seconds\n  akkaSystem.scheduler.scheduleOnce(20 seconds)(akkaSystem.shutdown())\n\n  val channels = Seq(\"time\")\n  val patterns = Seq(\"pattern.*\")\n  // create SubscribeActor instance\n  akkaSystem.actorOf(Props(classOf[SubscribeActor], channels, patterns).withDispatcher(\"rediscala.rediscala-client-worker-dispatcher\"))\n\n}\n\nclass SubscribeActor(channels: Seq[String] = Nil, patterns: Seq[String] = Nil) extends RedisSubscriberActor(channels, patterns) {\n  override val address: InetSocketAddress = new InetSocketAddress(\"localhost\", 6379)\n\n  def onMessage(message: Message) {\n    println(s\"message received: $message\")\n  }\n\n  def onPMessage(pmessage: PMessage) {\n    println(s\"pattern message received: $pmessage\")\n  }\n}\n```\n\nFull example: [ExamplePubSub](https://github.com/etaty/rediscala-demo/blob/master/src/main/scala/ExamplePubSub.scala)\n\nYou can fork with : `git clone git@github.com:etaty/rediscala-demo.git` then run it, with `sbt run`\n\n[RedisPubSubSpec](https://github.com/etaty/rediscala/blob/master/src/test/scala/redis/RedisPubSubSpec.scala) will reveal even more gems of the API.\n\n### Scripting\n\n`RedisScript` is a helper, you can put your LUA script inside and it will compute the hash. \nYou can use it with `evalshaOrEval` which run your script even if it wasn't already loaded.\n\n```scala\n  val redis = RedisClient()\n\n  val redisScript = RedisScript(\"return 'rediscala'\")\n\n  val r = redis.evalshaOrEval(redisScript).map({\n    case b: Bulk =\u003e println(b.toString())\n  })\n  Await.result(r, 5 seconds)\n```\n\nFull example: [ExampleScripting](https://github.com/etaty/rediscala-demo/blob/master/src/main/scala/ExampleScripting.scala)\n\n### Redis Sentinel\n\n[SentinelClient](http://etaty.github.io/rediscala/latest/api/index.html#redis.SentinelClient) connect to a redis sentinel server.\n\n[SentinelMonitoredRedisClient](http://etaty.github.io/rediscala/latest/api/index.html#redis.SentinelMonitoredRedisClient) connect to a sentinel server to find the master addresse then start a connection. In case the master change your RedisClient connection will automatically connect to the new master server.\nIf you are using a blocking client, you can use [SentinelMonitoredRedisBlockingClient](http://etaty.github.io/rediscala/latest/api/index.html#redis.SentinelMonitoredRedisBlockingClient)\n\n### Pool\n\n[RedisClientPool](http://etaty.github.io/rediscala/latest/api/index.html#redis.RedisClientPool) connect to a pool of redis servers.\nRedis commands are dispatched to redis connection in a round robin way.\n\n### Master Slave\n\n[RedisClientMasterSlaves](http://etaty.github.io/rediscala/latest/api/index.html#redis.RedisClientMasterSlaves) connect to a master and a pool of slaves.\nThe `write` commands are sent to the master, while the read commands are sent to the slaves in the [RedisClientPool](http://etaty.github.io/rediscala/latest/api/index.html#redis.RedisClientPool)\n\n### Config Which Dispatcher to Use\n\nBy default, the actors in this project will use the dispatcher `rediscala.rediscala-client-worker-dispatcher`. If you want to use another dispatcher, just config the implicit value of `redisDispatcher`:\n\n```scala\nimplicit val redisDispatcher = RedisDispatcher(\"akka.actor.default-dispatcher\")\n```\n\n### ByteStringSerializer ByteStringDeserializer ByteStringFormatter\n\n[ByteStringSerializer](http://etaty.github.io/rediscala/latest/api/index.html#redis.ByteStringSerializer)\n\n[ByteStringDeserializer](http://etaty.github.io/rediscala/latest/api/index.html#redis.ByteStringDeserializer)\n\n[ByteStringFormatter](http://etaty.github.io/rediscala/latest/api/index.html#redis.ByteStringFormatter)\n\n```scala\ncase class DumbClass(s1: String, s2: String)\n\nobject DumbClass {\n  implicit val byteStringFormatter = new ByteStringFormatter[DumbClass] {\n    def serialize(data: DumbClass): ByteString = {\n      //...\n    }\n\n    def deserialize(bs: ByteString): DumbClass = {\n      //...\n    }\n  }\n}\n//...\n\n  val dumb = DumbClass(\"s1\", \"s2\")\n\n  val r = for {\n    set \u003c- redis.set(\"dumbKey\", dumb)\n    getDumbOpt \u003c- redis.get[DumbClass](\"dumbKey\")\n  } yield {\n    getDumbOpt.map(getDumb =\u003e {\n      assert(getDumb == dumb)\n      println(getDumb)\n    })\n  }\n```\n\nFull example: [ExampleByteStringFormatter](https://github.com/etaty/rediscala-demo/blob/master/src/main/scala/ExampleByteStringFormatter.scala)\n\n### Scaladoc\n\n[Rediscala scaladoc API (version 1.9)](https://oss.sonatype.org/service/local/repositories/releases/archive/com/github/etaty/rediscala_2.12/1.9.0/rediscala_2.12-1.9.0-javadoc.jar/!/redis/index.html)\n\n[Rediscala scaladoc API (version 1.8)](https://oss.sonatype.org/service/local/repositories/releases/archive/com/github/etaty/rediscala_2.11/1.8.0/rediscala_2.11-1.8.0-javadoc.jar/!/index.html#package)\n\n[Rediscala scaladoc API (version 1.7)](https://oss.sonatype.org/service/local/repositories/releases/archive/com/github/etaty/rediscala_2.11/1.7.0/rediscala_2.11-1.7.0-javadoc.jar/!/index.html#package)\n\n[Rediscala scaladoc API (version 1.6)](http://etaty.github.io/rediscala/1.6.0/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.5)](http://etaty.github.io/rediscala/1.5.0/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.4)](http://etaty.github.io/rediscala/1.4.0/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.3)](http://etaty.github.io/rediscala/1.3/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.2)](http://etaty.github.io/rediscala/1.2/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.1)](http://etaty.github.io/rediscala/1.1/api/index.html#package)\n\n[Rediscala scaladoc API (version 1.0)](http://etaty.github.io/rediscala/1.0/api/index.html#package)\n\n### Performance\n\nMore than 250 000 requests/second\n\n* [benchmark result from scalameter](http://bit.ly/rediscalabench-1-1)\n* [sources directory](https://github.com/etaty/rediscala/tree/master/src/benchmark/scala/redis/bench)\n\nThe hardware used is a macbook retina (Intel Core i7, 2.6 GHz, 4 cores, 8 threads, 8GB) running the sun/oracle jvm 1.6\n\nYou can run the bench with :\n\n1. clone the repo `git clone git@github.com:etaty/rediscala.git`\n2. run `sbt bench:test`\n3. open the bench report `rediscala/tmp/report/index.html`\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fetaty%2Frediscala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fetaty%2Frediscala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fetaty%2Frediscala/lists"}