{"id":15664378,"url":"https://github.com/knutwalker/rx-redis","last_synced_at":"2025-05-06T19:10:38.428Z","repository":{"id":18711422,"uuid":"21922139","full_name":"knutwalker/rx-redis","owner":"knutwalker","description":"Reactive Redis client on top of RxJava on Netty","archived":false,"fork":false,"pushed_at":"2018-10-29T11:33:07.000Z","size":1056,"stargazers_count":16,"open_issues_count":4,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-03T13:42:44.870Z","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/knutwalker.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-07-16T23:48:39.000Z","updated_at":"2022-07-03T16:43:22.000Z","dependencies_parsed_at":"2022-09-26T22:01:33.035Z","dependency_job_id":null,"html_url":"https://github.com/knutwalker/rx-redis","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Frx-redis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Frx-redis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Frx-redis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Frx-redis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knutwalker","download_url":"https://codeload.github.com/knutwalker/rx-redis/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221152505,"owners_count":16765054,"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-10-03T13:42:20.679Z","updated_at":"2024-10-23T03:41:33.544Z","avatar_url":"https://github.com/knutwalker.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Travis CI](https://img.shields.io/travis/knutwalker/rx-redis/master.svg)](https://travis-ci.org/knutwalker/rx-redis)\n[![Coverage Status](https://img.shields.io/coveralls/knutwalker/rx-redis/master.svg)](https://coveralls.io/r/knutwalker/rx-redis)\n[![Maven](https://img.shields.io/maven-central/v/de.knutwalker/rx-redis-scala_2.11.svg)](http://search.maven.org/#search|ga|1|g%3A%22de.knutwalker%22%20AND%20a%3Arx-redis-*_2.11)\n[![Apache License](https://img.shields.io/badge/license-APACHE_2-green.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nRxRedis\n========\n\nReactive Extensions for Redis.\n\n## Motivation\n###### Or why yet another redis client\n\nRxRedis is a client for [redis](http://redis.io).\nIt is different from other clients, in that it's using [Reactive Extensions](http://reactivex.io/) for its API.\n\nUsing RxJava allows for some nice abstractions. So is, for example, the return type of `GET` and `MGET` identical; It's just, that the Observable of `GET` completes after the first value.\n\n## Overview\n\nRxRedis is written for Scala 2.11 and Java 8 and has different language specific bindings for each of them. It uses Netty under the hood for network transportation and RxJava for its API. RxRedis itself is written in Scala.\n\nRxRedis comes with a small type tree for the Redis Serialization Protocol (RESP), a netty pipeline, that can send and receive such RESP types, and a client, that hides this pipeline behind RxJava.\n\n\n## Installation\n\nRxRedis can be obtained from [Maven Central](http://search.maven.org/#search|ga|1|g%3A%22de.knutwalker%22%20AND%20a%3Arx-redis-*_2.11%20AND%20v%3A%220.3.0%22).\n\nThe main artifacts are `rx-redis-java_2.11` for the Java binding and `rx-redis-scala_2.11` for the Scala binding. The current version is 0.3.0.\n\nFor maven:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003ede.knutwalker\u003c/groupId\u003e\n        \u003cartifactId\u003erx-redis-java_2.11\u003c/artifactId\u003e\n        \u003cversion\u003e0.3.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\n\nFor sbt:\n\n    libraryDependencies += \"de.knutwalker\" %% \"rx-redis-scala\" % \"0.3.0\"\n\n\nRxRedis has a dependency on Netty and RxJava. The Scala binding also depend on the Scala bindings of RxJava.\nAs it is written in Scala, RxRedis also depends on scala-library and the scala-reflect module, though I'm trying to get the last one out of the runtime classpath. Here's the full graph (except for scala-library):\n\n\u003ca href=\"https://raw.githubusercontent.com/knutwalker/rx-redis/v0.3.0/dependency-graph.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/knutwalker/rx-redis/v0.3.0/dependency-graph.png\" alt=\"dependency-graph\" width=\"640\" height=\"171\"\u003e\u003c/a\u003e\n\n\n`rx-redis-parent` is the umbrella artifact and should not be used.\n\n`rx-redis-client` is a raw client, that supports the complete API, but is more or less inconvenient to use from your target language.\n\n`rx-redis-pipeline` contains the netty pipeline. It could also be used for a different client that uses Netty.\n\n`rx-redis-core` contains the RESP types and all type class definitions. Additional support libraries or modules (e.g. for Jackson Support) only need to depend on this artifact.\n\n\n\n## Usage\n\nRxRedis only exposes its API with RxJava, thus it only supports asynchronous execution and has no built-in synchronous client. That being said, there is a `Observable::toBlocking()` method, to get effectively blocking behaviour.\n\n\n### Scala\n\n\n```scala\n\nimport rx.redis.api.RxRedis\n\nval client = RxRedis(\"localhost\", 6379)\nclient.set(\"foo\", \"bar\")\nclient.get(\"foo\").foreach(println)\n\nclient.del(\"foo\").doOnCompleted(client.shutdown()).subscribe()\nRxRedis.await(client)\n\n```\n\n\n### Java\n\n\n```java\n\nimport rx.redis.japi.RxRedis;\nimport rx.redis.japi.Client;\n\n...\n\nfinal Client client = RxRedis.connect(\"localhost\", 6379);\nclient.set(\"foo\", \"bar\");\nclient.get(\"foo\").forEach(System.out::println);\n\nclient.del(\"foo\").doOnCompleted(client::shutdown).subscribe();\nRxRedis.await(client);\n\n```\n\n\nThe examples are very similar and probably not much suprising.\nTwo things to point out:\n\n1. The call to `client.xxx.doOnCompleted(client.shutdown()).subscribe()`.\n    \n    doOnComplete notifies the client, that it should shutdown after this command has completed.\n    The `subscribe` is necessary, so that the callback actually fires. Without subscription, the onCompleted message would be lost.\n2. The call to `RxRedis.await(client)`.\n\n    Since the call to any command is asynchronous, you can't just close the client at the end of your script, since the commands might be fliying around the network. `RxRedis.await` is a helper, that blocks until the last response from the server was delivered to the client. This requires, that you call `client.shutdown()` at some point, otherwise `await` would block forever.\n\n\nAn instance of this Client is thread-safe, almost all operations are executed on nettys event loop.\n\n\n### Custom types\n\nYou can send arbitrary types (POJOs) with RxRedis. All you have to do is implement an instance of `rs.redis.serialization.BytesFormat` for your type. For Scala: this is a type class and should be made implicitly available. Commands that support custom types end on `As` and are parameterized in their type.\n\n#### Scala\n\n\n```scala\n\n// given implicit evidence of BytesFormat[Person]\nclient.setAs(\"danger\", Person(\"Heisenberg\"))\nclient.getAs[Person](\"danger\")\n\n```\n\n#### Java\n\n\n```java\n\nBytesFormat\u003cPerson\u003e personFormat = ...;\nclient.setAs(\"danger\", new Person(\"Heisenberg\"), personFormat);\nclient.getAs(\"danger\", personFormat);\n\n```\n\nThe trait/interface `BytesFormat` has two simple methods: `bytes` and `value` for transforming your type into an byte array and back.\n\n\nFor Scala, instances for `String`, `Array[Byte]`, `Long`, `Duration`, and `Deadline` are provided.\n\nFor Java, these instances are available in `rx.redis.japi.DefaultBytes.*`.\n\n\n### Arbitrary commands\n\nAt the moment, very few commands are actually implemented. However, you still have the possibility to send anything you want. You just pass a string that you would have entered in the redis-cli, for example.\n\n#### Scala\n\n\n```scala\n\nimport rx.redis._\n\nclient.command(cmd\"INFO SERVER\")\nval part = \"memory\"\nclient.command(cmd\"INFO $part\")\n\n```\n\n\n#### Java\n\n\n```java\n\nclient.command(RxRedis.command(\"INFO SERVER\"));\nString part = \"memeory\";\nclient.command(RxRedis.command(\"INFO \" + part));\n\n```\n\n\nIn addition to that, there is a type class `rx.redis.serialization.Writes`, that is used to determin how a type `A` gets transformed into the Redis Serialzation Protocol (RESP).\nFor every command, there exists a case class and a macro generates the implementation of `Writes` for this case class.\nThe client APIs then just send a new instance of some case class to the netty pipeline.\n\nYou can also send any `A` for which you can provide an instance of `Writes[A]`.\n\n\n## Working with the Source\n\nRxRedis is built with sbt and comes with a launch script, you only need a JDK installed. After downloading/cloning, run `./sbt` to drop into the sbt shell. Some things to can do there, besides `compile` and `test`:\n\n- `example/run` to run the Scala examples\n- `java-example/run` to run the Java examples\n- `it:test` to tun integration tests, need a Redis instance running **DB 0 will be deleted!**\n- `reg:test` to run regression tests (codec tests)\n- `publishM2` to install the snapshot version locally\n\n\n## Future\n\nPlans for future versions (in no particular order or timeline):\n\n- Support all commands in the API\n- Support for transactions (MULTI/EXEC)\n- Support for Redis Cluster\n- Connection pooling/client-side cluster\n- Possible support for pipelining (maybe transparent to transactions)\n- Support for backpressure, reconnecting clients, etc.\n- Cross compile for Scala 2.10, maybe also for Java 7\n- BytesFormat implementation for typical data formats, such as Json (e.g. Jackson, Gson, various Scala ones), Protobuf, etc...\n- Language binding for Clojure (Groovy, Kotlin, ...? Basically, anything that is supported by RxJava)\n- Abstract backend implementation, build on reactive-streams am make backend pluggable (e.g. RxNetty, Akka streams, ...)\n- ...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Frx-redis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknutwalker%2Frx-redis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Frx-redis/lists"}