├── settings.gradle ├── .travis.yml ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── setup.gradle ├── maven.gradle └── vertx.gradle ├── .gitignore ├── mod ├── src │ ├── main │ │ ├── java │ │ │ └── io │ │ │ │ └── vertx │ │ │ │ └── redis │ │ │ │ ├── impl │ │ │ │ ├── ReplyHandler.java │ │ │ │ ├── MessageHandler.java │ │ │ │ ├── RedisAsyncResult.java │ │ │ │ └── RedisSubscriptions.java │ │ │ │ ├── Reply.java │ │ │ │ ├── ReplyParser.java │ │ │ │ ├── Command.java │ │ │ │ ├── RedisMod.java │ │ │ │ └── RedisConnection.java │ │ └── resources │ │ │ └── mod.json │ └── test │ │ ├── java │ │ └── io │ │ │ └── vertx │ │ │ └── redis │ │ │ ├── ReplyParserTester.java │ │ │ ├── RedisInfoTester.java │ │ │ ├── Issue26.java │ │ │ ├── EvalTester.java │ │ │ ├── LoadTester.java │ │ │ └── RedisClientTester.java │ │ └── groovy │ │ └── io │ │ └── vertx │ │ └── redis │ │ └── GRedisPubSubTester.groovy ├── gradle.properties └── build.gradle ├── LICENSE.txt ├── mod-client ├── gradle.properties ├── src │ ├── main │ │ ├── resources │ │ │ ├── mod.json │ │ │ └── abstractRedisClient.js │ │ ├── groovy │ │ │ └── io │ │ │ │ └── vertx │ │ │ │ └── groovy │ │ │ │ └── redis │ │ │ │ ├── AbstractRedisClient.groovy │ │ │ │ ├── RedisCommand.groovy │ │ │ │ └── RedisClient.java │ │ └── java │ │ │ └── io │ │ │ └── vertx │ │ │ └── java │ │ │ └── redis │ │ │ ├── RedisCommand.java │ │ │ ├── AbstractRedisClient.java │ │ │ └── RedisClient.java │ └── test │ │ ├── resources │ │ └── jsModRedisTest.js │ │ ├── java │ │ └── io │ │ │ └── vertx │ │ │ └── redis │ │ │ ├── JSRedisModTest.java │ │ │ ├── RedisModTestWithSelect.java │ │ │ └── RedisModTest.java │ │ └── groovy │ │ └── io │ │ └── vertx │ │ └── redis │ │ ├── GRedisModTest.groovy │ │ └── Generate.groovy └── build.gradle ├── gradle.properties ├── gradlew.bat ├── gradlew └── README.md /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'mod' 2 | include 'mod-client' -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk7 4 | - oraclejdk7 5 | services: redis 6 | env: TRAVISCI=1 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x/mod-redis/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | mods 3 | .idea 4 | *.iml 5 | *.ipr 6 | *.iws 7 | .gradle 8 | .classpath 9 | .project 10 | .settings 11 | build 12 | -------------------------------------------------------------------------------- /gradle/setup.gradle: -------------------------------------------------------------------------------- 1 | 2 | task wrapper(type: Wrapper, description: "Create a Gradle self-download wrapper") { 3 | group = 'Project Setup' 4 | gradleVersion = rootProject.gradleVersion 5 | } -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/impl/ReplyHandler.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis.impl; 2 | 3 | import io.vertx.redis.Reply; 4 | 5 | public interface ReplyHandler { 6 | 7 | void handleReply(Reply reply); 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | vert.x is licensed under the Apache License, Version 2.0 (the "License"); 2 | you may not use this file except in compliance with the License. 3 | 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 -------------------------------------------------------------------------------- /mod-client/gradle.properties: -------------------------------------------------------------------------------- 1 | # E.g. your domain name 2 | modowner=io.vertx 3 | 4 | # Your module name 5 | modname=mod-redis-client 6 | 7 | # The test timeout in seconds 8 | testtimeout=300 9 | 10 | # The version of Vert.x Groovy 11 | groovyLangModVersion=2.0.0-final 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jan 28 08:12:12 GMT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip 7 | -------------------------------------------------------------------------------- /mod/gradle.properties: -------------------------------------------------------------------------------- 1 | # E.g. your domain name 2 | modowner=io.vertx 3 | 4 | # Your module name 5 | modname=mod-redis 6 | 7 | # The test timeout in seconds 8 | testtimeout=300 9 | 10 | # Set to true if you want module dependencies to be pulled in and nested inside the module itself 11 | pullInDeps=false 12 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/impl/MessageHandler.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis.impl; 2 | 3 | import io.vertx.redis.Reply; 4 | 5 | /** 6 | * An interface mainly created to pass 2 parameters to pub/sub message handler (thus avoiding double casts) 7 | */ 8 | public interface MessageHandler { 9 | public void handle(String channelOrPattern, Reply[] replyData); 10 | } 11 | -------------------------------------------------------------------------------- /mod-client/src/main/resources/mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Redis client API for Vert.x 2.x", 3 | "licenses": ["The Apache Software License Version 2.0"], 4 | "author": "Paulo Lopes ", 5 | 6 | "developers": ["pmlopes"], 7 | "keywords": ["redis", "eventbus"], 8 | "homepage": "https://github.com/vert-x/mod-redis", 9 | 10 | "deploys": "io.vertx~mod-redis~1.1.4" 11 | } 12 | -------------------------------------------------------------------------------- /mod/src/main/resources/mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "io.vertx.redis.RedisMod", 3 | 4 | "description": "Asynchronous REDIS module for Vert.x", 5 | "licenses": ["The Apache Software License Version 2.0"], 6 | "author": "Paulo Lopes ", 7 | 8 | "developers": ["pmlopes"], 9 | "keywords": ["redis", "eventbus", "connector", "client", "asynchronous"], 10 | "homepage": "https://github.com/vert-x/mod-redis" 11 | } 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Your module version 2 | version=1.1.6-SNAPSHOT 3 | 4 | # The test timeout in seconds 5 | testtimeout=300 6 | 7 | # Set to true if you want module dependencies to be pulled in and nested inside the module itself 8 | pullInDeps=true 9 | 10 | # Set to true if you want the build to output a jar as well as a module zip file 11 | produceJar=true 12 | 13 | # The version of Groovy to use (if you are using Groovy) 14 | groovyVersion=2.2.1 15 | 16 | # Gradle version 17 | gradleVersion=1.10 18 | 19 | # The version of Vert.x 20 | vertxVersion=2.1.6 21 | 22 | # The version of Vert.x test tools 23 | toolsVersion=2.0.3-final 24 | 25 | # The version of JUnit 26 | junitVersion=4.11 27 | -------------------------------------------------------------------------------- /mod-client/src/test/resources/jsModRedisTest.js: -------------------------------------------------------------------------------- 1 | var container = require("vertx/container"); 2 | var vertx = require("vertx"); 3 | var vertxTests = require("vertx_tests"); 4 | var vassert = require("vertx_assert"); 5 | 6 | 7 | var RedisClient = require("redisClient"); 8 | 9 | function testClient() { 10 | var redis = new RedisClient("test.redis.api.client"); 11 | 12 | redis.deployModule({}, 1, function (err) { 13 | if (err) { 14 | return vassert.fail(err); 15 | } 16 | redis.set("key", "value", function (reply) { 17 | 18 | redis.get("key", function (reply) { 19 | 20 | vassert.assertEquals("value", reply.value); 21 | vassert.testComplete(); 22 | }); 23 | }); 24 | }); 25 | } 26 | 27 | vertxTests.startTests(this); -------------------------------------------------------------------------------- /mod-client/src/test/java/io/vertx/redis/JSRedisModTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.vertx.testtools.ScriptClassRunner; 6 | import org.vertx.testtools.TestVerticleInfo; 7 | 8 | /** 9 | * This is dummy JUnit test class which is used to run any JavaScript test scripts as JUnit tests. 10 | * 11 | * The scripts by default go in src/test/resources/integration_tests 12 | * 13 | * If you don't have any JavaScript tests in your project you can delete this 14 | * 15 | * You do not need to edit this file unless you want it to look for tests elsewhere 16 | */ 17 | @TestVerticleInfo(filenameFilter=".+\\.js", funcRegex="function[\\s]+(test[^\\s(]+)") 18 | @RunWith(ScriptClassRunner.class) 19 | public class JSRedisModTest { 20 | @Test 21 | public void __vertxDummy() { 22 | } 23 | } -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/impl/RedisAsyncResult.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis.impl; 2 | 3 | import org.vertx.java.core.AsyncResult; 4 | 5 | public class RedisAsyncResult implements AsyncResult { 6 | 7 | private final Throwable cause; 8 | private final T result; 9 | 10 | public RedisAsyncResult(Throwable cause) { 11 | this(cause, null); 12 | } 13 | 14 | public RedisAsyncResult(Throwable cause, T result) { 15 | this.cause = cause; 16 | this.result = result; 17 | } 18 | @Override 19 | public T result() { 20 | return result; 21 | } 22 | 23 | @Override 24 | public Throwable cause() { 25 | return cause; 26 | } 27 | 28 | @Override 29 | public boolean succeeded() { 30 | return cause == null; 31 | } 32 | 33 | @Override 34 | public boolean failed() { 35 | return cause != null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/ReplyParserTester.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.redis.impl.ReplyHandler; 4 | import org.junit.Test; 5 | import org.vertx.java.core.buffer.Buffer; 6 | import org.vertx.testtools.TestVerticle; 7 | 8 | import static org.vertx.testtools.VertxAssert.*; 9 | 10 | public class ReplyParserTester extends TestVerticle { 11 | 12 | @Test 13 | public void testArrayArrayParser() { 14 | Buffer b = new Buffer(); 15 | b.appendString( 16 | "*2\r\n" + 17 | "*3\r\n" + 18 | ":1\r\n" + 19 | ":2\r\n" + 20 | ":3\r\n" + 21 | "*2\r\n" + 22 | "+Foo\r\n" + 23 | "-Bar\r\n"); 24 | 25 | ReplyParser parser = new ReplyParser(new ReplyHandler() { 26 | @Override 27 | public void handleReply(Reply reply) { 28 | testComplete(); 29 | } 30 | }); 31 | 32 | parser.handle(b); 33 | } 34 | 35 | @Test 36 | public void testArrayArrayEmptyParser() { 37 | Buffer b = new Buffer(); 38 | b.appendString( 39 | "*1\r\n" + 40 | "*0\r\n"); 41 | 42 | ReplyParser parser = new ReplyParser(new ReplyHandler() { 43 | @Override 44 | public void handleReply(Reply reply) { 45 | testComplete(); 46 | } 47 | }); 48 | 49 | parser.handle(b); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/impl/RedisSubscriptions.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis.impl; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class RedisSubscriptions { 7 | 8 | private final Map channelSubscribers = new HashMap<>(); 9 | private final Map patternSubscribers = new HashMap<>(); 10 | 11 | public void registerChannelSubscribeHandler(String channel, MessageHandler messageHandler) { 12 | channelSubscribers.put(channel, messageHandler); 13 | } 14 | 15 | public void registerPatternSubscribeHandler(String pattern, MessageHandler messageHandler) { 16 | patternSubscribers.put(pattern, messageHandler); 17 | } 18 | 19 | public void unregisterChannelSubscribeHandler(String channel) { 20 | if (channel == null) { 21 | channelSubscribers.clear(); 22 | } else { 23 | channelSubscribers.remove(channel); 24 | } 25 | } 26 | 27 | public void unregisterPatternSubscribeHandler(String pattern) { 28 | if (pattern == null) { 29 | patternSubscribers.clear(); 30 | } else { 31 | patternSubscribers.remove(pattern); 32 | } 33 | } 34 | 35 | public MessageHandler getChannelHandler(String channel) { 36 | return channelSubscribers.get(channel); 37 | } 38 | 39 | public MessageHandler getPatternHandler(String pattern) { 40 | return patternSubscribers.get(pattern); 41 | } 42 | 43 | public int channelSize() { 44 | return channelSubscribers.size(); 45 | } 46 | 47 | public int patternSize() { 48 | return patternSubscribers.size(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /mod-client/src/test/groovy/io/vertx/redis/GRedisModTest.groovy: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.groovy.redis.RedisClient; 4 | import org.junit.Test; 5 | import org.vertx.java.core.AsyncResult; 6 | import org.vertx.java.core.AsyncResultHandler; 7 | import org.vertx.groovy.core.eventbus.EventBus; 8 | 9 | import org.vertx.java.core.json.JsonObject; 10 | import org.vertx.testtools.TestVerticle; 11 | 12 | import static org.vertx.testtools.VertxAssert.*; 13 | 14 | public class GRedisModTest extends TestVerticle { 15 | 16 | private final String address = "test.redis.api.client"; 17 | 18 | private RedisClient client; 19 | 20 | private void appReady() { 21 | super.start(); 22 | } 23 | private static String makeKey() { 24 | return UUID.randomUUID().toString(); 25 | } 26 | 27 | public void start() { 28 | initialize(vertx) 29 | final EventBus eb = new EventBus(vertx.eventBus()); 30 | JsonObject config = new JsonObject(); 31 | 32 | config.putString("address", address); 33 | 34 | container.deployModule("io.vertx~mod-redis~1.1.4", config, 1, new AsyncResultHandler() { 35 | @Override 36 | public void handle(AsyncResult event) { 37 | if (event.failed()) { 38 | fail(event.cause().getMessage()); 39 | } else { 40 | client = new RedisClient(eb, address); 41 | appReady(); 42 | } 43 | } 44 | }); 45 | } 46 | @Test 47 | public void testSetGet() { 48 | final String key = makeKey(); 49 | client.set(key, "value1") { reply -> 50 | assertEquals("ok", reply.body["status"]); 51 | 52 | client.get(key) { reply1 -> 53 | assertEquals("ok", reply1.body["status"]); 54 | assertEquals("value1", reply1.body["value"]); 55 | testComplete(); 56 | }; 57 | }; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /mod-client/src/test/java/io/vertx/redis/RedisModTestWithSelect.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.java.redis.RedisClient; 4 | import org.junit.Test; 5 | import org.vertx.java.core.AsyncResult; 6 | import org.vertx.java.core.AsyncResultHandler; 7 | import org.vertx.java.core.Handler; 8 | import org.vertx.java.core.eventbus.EventBus; 9 | import org.vertx.java.core.eventbus.Message; 10 | import org.vertx.java.core.json.JsonObject; 11 | import org.vertx.testtools.TestVerticle; 12 | import org.vertx.testtools.VertxAssert; 13 | 14 | import java.util.UUID; 15 | 16 | import static org.vertx.testtools.VertxAssert.*; 17 | 18 | public class RedisModTestWithSelect extends TestVerticle { 19 | 20 | private final String address = "test.redis.api.client"; 21 | private EventBus eb; 22 | 23 | private RedisClient client; 24 | 25 | private void appReady() { 26 | super.start(); 27 | } 28 | private static String makeKey() { 29 | return UUID.randomUUID().toString(); 30 | } 31 | 32 | public void start() { 33 | VertxAssert.initialize(vertx); 34 | eb = vertx.eventBus(); 35 | 36 | client = new RedisClient(eb, address); 37 | 38 | client.deployModule(container, "localhost", 6379, "UTF-8", false, null, 1, 1, new AsyncResultHandler() { 39 | @Override 40 | public void handle(AsyncResult event) { 41 | if (event.failed()) { 42 | fail(event.cause().getMessage()); 43 | } else { 44 | client = new RedisClient(eb, address); 45 | appReady(); 46 | } 47 | } 48 | }); 49 | } 50 | 51 | @Test 52 | public void testSetGet() { 53 | final String key = makeKey(); 54 | client.set(key, "value1", new Handler>() { 55 | @Override 56 | public void handle(Message reply) { 57 | assertEquals("ok", reply.body().getString("status")); 58 | 59 | client.get(key, new Handler>() { 60 | 61 | @Override 62 | public void handle(Message reply) { 63 | assertEquals("ok", reply.body().getString("status")); 64 | assertEquals("value1", reply.body().getString("value")); 65 | testComplete(); 66 | } 67 | }); 68 | } 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /mod-client/src/test/java/io/vertx/redis/RedisModTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.java.redis.RedisClient; 4 | import org.junit.Test; 5 | import org.vertx.java.core.AsyncResult; 6 | import org.vertx.java.core.AsyncResultHandler; 7 | import org.vertx.java.core.Handler; 8 | import org.vertx.java.core.eventbus.EventBus; 9 | import org.vertx.java.core.eventbus.Message; 10 | import org.vertx.java.core.json.JsonObject; 11 | import org.vertx.testtools.TestVerticle; 12 | import org.vertx.testtools.VertxAssert; 13 | 14 | import java.util.UUID; 15 | 16 | import static org.vertx.testtools.VertxAssert.*; 17 | 18 | public class RedisModTest extends TestVerticle { 19 | 20 | private final String address = "test.redis.api.client"; 21 | private EventBus eb; 22 | 23 | private RedisClient client; 24 | 25 | private void appReady() { 26 | super.start(); 27 | } 28 | private static String makeKey() { 29 | return UUID.randomUUID().toString(); 30 | } 31 | 32 | public void start() { 33 | VertxAssert.initialize(vertx); 34 | eb = vertx.eventBus(); 35 | JsonObject config = new JsonObject(); 36 | 37 | config.putString("address", address); 38 | 39 | container.deployModule("io.vertx~mod-redis~1.1.4", config, 1, new AsyncResultHandler() { 40 | @Override 41 | public void handle(AsyncResult event) { 42 | if (event.failed()) { 43 | fail(event.cause().getMessage()); 44 | } else { 45 | client = new RedisClient(eb, address); 46 | appReady(); 47 | } 48 | } 49 | }); 50 | } 51 | @Test 52 | public void testSetGet() { 53 | final String key = makeKey(); 54 | client.set(key, "value1", new Handler>() { 55 | @Override 56 | public void handle(Message reply) { 57 | assertEquals("ok", reply.body().getString("status")); 58 | 59 | client.get(key, new Handler>() { 60 | 61 | @Override 62 | public void handle(Message reply) { 63 | assertEquals("ok", reply.body().getString("status")); 64 | assertEquals("value1", reply.body().getString("value")); 65 | testComplete(); 66 | } 67 | }); 68 | } 69 | }); 70 | } 71 | @Test 72 | public void testArgumentlessPing() { 73 | client.ping(); 74 | testComplete(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /gradle/maven.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply plugin: 'maven' 18 | apply plugin: 'signing' 19 | 20 | if (!hasProperty('sonatypeUsername')) { 21 | // try to see if the variables are set as environment variables 22 | ext.sonatypeUsername = System.getenv('CI_SONATYPE_USERNAME') 23 | if (ext.sonatypeUsername == null) { 24 | ext.sonatypeUsername = '' 25 | } 26 | } 27 | if (!hasProperty('sonatypePassword')) { 28 | // try to see if the variables are set as environment variables 29 | ext.sonatypePassword = System.getenv('CI_SONATYPE_PASSWORD') 30 | if (ext.sonatypePassword == null) { 31 | ext.sonatypePassword = '' 32 | } 33 | } 34 | 35 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | // maven task configuration 37 | 38 | ext.isReleaseVersion = !version.endsWith("SNAPSHOT") 39 | 40 | signing { 41 | required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") } 42 | sign configurations.archives 43 | } 44 | 45 | uploadArchives { 46 | group 'build' 47 | description = "Does a maven deploy of archives artifacts" 48 | 49 | repositories { 50 | mavenDeployer { 51 | // setUniqueVersion(false) 52 | 53 | configuration = configurations.archives 54 | 55 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 56 | authentication(userName: sonatypeUsername, password: sonatypePassword) 57 | } 58 | 59 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 60 | authentication(userName: sonatypeUsername, password: sonatypePassword) 61 | } 62 | 63 | if (isReleaseVersion) { 64 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 65 | } 66 | 67 | configurePom(pom) 68 | } 69 | } 70 | } 71 | 72 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | // configuration methods 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/RedisInfoTester.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.vertx.java.core.AsyncResult; 5 | import org.vertx.java.core.AsyncResultHandler; 6 | import org.vertx.java.core.Handler; 7 | import org.vertx.java.core.eventbus.EventBus; 8 | import org.vertx.java.core.eventbus.Message; 9 | import org.vertx.java.core.json.JsonObject; 10 | import org.vertx.testtools.TestVerticle; 11 | import org.vertx.testtools.VertxAssert; 12 | 13 | import static org.vertx.testtools.VertxAssert.*; 14 | 15 | public class RedisInfoTester extends TestVerticle { 16 | 17 | private final String address = "test.redis.info"; 18 | private EventBus eb; 19 | 20 | private void appReady() { 21 | super.start(); 22 | } 23 | 24 | public void start() { 25 | VertxAssert.initialize(vertx); 26 | eb = vertx.eventBus(); 27 | JsonObject config = new JsonObject(); 28 | 29 | config.putString("address", address); 30 | 31 | container.deployModule(System.getProperty("vertx.modulename"), config, 1, new AsyncResultHandler() { 32 | @Override 33 | public void handle(AsyncResult event) { 34 | appReady(); 35 | } 36 | }); 37 | } 38 | 39 | /** 40 | * Helper method to allow simple Groovy closure calls and simplified maps as json messages 41 | * @param json message 42 | * @param handler response handler 43 | */ 44 | void redis(final String json, final boolean fail, final Handler> handler) { 45 | eb.send(address, new JsonObject(json), new Handler>() { 46 | public void handle(Message reply) { 47 | if (fail) { 48 | assertEquals("error", reply.body().getString("status")); 49 | } else { 50 | assertEquals("ok", reply.body().getString("status")); 51 | } 52 | 53 | handler.handle(reply); 54 | } 55 | }); 56 | } 57 | 58 | @Test 59 | public void testInfo() { 60 | 61 | redis("{\"command\":\"info\"}", false, new Handler>() { 62 | @Override 63 | public void handle(Message reply) { 64 | JsonObject server = reply.body().getObject("value").getObject("server"); 65 | if (server == null) { 66 | server = reply.body().getObject("value"); 67 | } 68 | assertTrue(server.getString("redis_version").startsWith("2.") || server.getString("redis_version").startsWith("3.")); 69 | testComplete(); 70 | } 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /mod-client/src/main/resources/abstractRedisClient.js: -------------------------------------------------------------------------------- 1 | var container = require("vertx/container"); 2 | var vertx = require("vertx"); 3 | 4 | module.exports = function (redisAddress) { 5 | this.eventBus = vertx.eventBus; 6 | }; 7 | 8 | module.exports.prototype.init = function (redisAddress) { 9 | this.redisAddress = redisAddress; 10 | }; 11 | 12 | module.exports.prototype.deployModule = function (options, instances, handler) { 13 | 14 | var config = { 15 | hostname: options.hostname || "localhost", 16 | port: options.port || 6379, 17 | address: this.redisAddress, 18 | encoding: options.encoding || "UTF-8", 19 | binary: options.binary || false, 20 | auth: options.auth || null, 21 | select: options.select || 0 22 | }; 23 | 24 | if (arguments.length === 2) { 25 | if (typeof instances === "function") { 26 | handler = instances; 27 | instances = 1; 28 | } 29 | } 30 | 31 | var mod = "io.vertx~mod-redis~1.1.5"; 32 | 33 | if (handler) { 34 | container.deployModule(mod, config, instances, handler); 35 | } else { 36 | container.deployModule(mod, config, instances); 37 | } 38 | }; 39 | 40 | module.exports.prototype.send = function(command, args) { 41 | var json = {command: command, args: []}; 42 | var totalArgs = 0; 43 | var messageHandler = null; 44 | 45 | // verify if there are args 46 | if (args != null) { 47 | // verify if the last one is a Handler 48 | var last = args[args.length - 1]; 49 | totalArgs = args.length; 50 | if (last instanceof Function) { 51 | // the caller expects a result 52 | totalArgs--; 53 | messageHandler = last; 54 | } 55 | } 56 | 57 | // handle special hash commands 58 | if ("MSET" === command || "MSETNX" === command || "HMSET" === command || "ZADD" === command) { 59 | if (totalArgs == 2 && args[1] instanceof Object) { 60 | // there are only 2 arguments and the last is a json object, convert the hash into a redis command 61 | json.args.push(args[0]); 62 | for (var key in args[1]) { 63 | if (args[1].hasOwnProperty(key)) { 64 | json.args.push(key); 65 | json.args.push(args[1][key]); 66 | } 67 | } 68 | // remove these 2 since they are already added to the args array 69 | totalArgs = 0; 70 | } 71 | } 72 | 73 | // serialize arguments 74 | for (var i = 0; i < totalArgs; i++) { 75 | json.args.push(args[i]); 76 | } 77 | 78 | if (messageHandler) { 79 | this.eventBus.send(this.redisAddress, json, messageHandler); 80 | } else { 81 | this.eventBus.send(this.redisAddress, json); 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/Issue26.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.vertx.java.core.AsyncResult; 5 | import org.vertx.java.core.AsyncResultHandler; 6 | import org.vertx.java.core.Handler; 7 | import org.vertx.java.core.eventbus.EventBus; 8 | import org.vertx.java.core.eventbus.Message; 9 | import org.vertx.java.core.json.JsonArray; 10 | import org.vertx.java.core.json.JsonObject; 11 | import org.vertx.testtools.TestVerticle; 12 | import org.vertx.testtools.VertxAssert; 13 | 14 | import static org.vertx.testtools.VertxAssert.*; 15 | 16 | public class Issue26 extends TestVerticle { 17 | 18 | private final String address = "test.redis.load"; 19 | private EventBus eb; 20 | 21 | private void appReady() { 22 | super.start(); 23 | } 24 | 25 | @Override 26 | public void start() { 27 | VertxAssert.initialize(vertx); 28 | eb = vertx.eventBus(); 29 | JsonObject config = new JsonObject(); 30 | 31 | config.putString("address", address); 32 | 33 | container.deployModule(System.getProperty("vertx.modulename"), config, 1, new AsyncResultHandler() { 34 | @Override 35 | public void handle(AsyncResult event) { 36 | appReady(); 37 | } 38 | }); 39 | } 40 | 41 | @Test 42 | public void testLongMessages() { 43 | 44 | // setup 45 | final String testKey = "testKey"; 46 | JsonObject command = new JsonObject(); 47 | command.putString("command", "hmset"); 48 | 49 | JsonArray args = new JsonArray(); 50 | args.add(testKey); 51 | for (int i=0; i<1000; i++) { 52 | args.add("field"+i); 53 | args.add("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 54 | } 55 | command.putArray("args", args); 56 | 57 | eb.send(address, command, new Handler>() { 58 | @Override 59 | public void handle(Message result) { 60 | //key should be stored 61 | 62 | //now hgetall the key 63 | final JsonObject command = new JsonObject(); 64 | JsonArray args = new JsonArray(); 65 | args.add(testKey); 66 | command.putString("command", "hgetall"); 67 | command.putArray("args", args); 68 | 69 | eb.send(address, command, new Handler>() { 70 | @Override 71 | public void handle(Message result) { 72 | System.out.println(result.body().getObject("value").size()); 73 | 74 | eb.send(address, command, new Handler>() { 75 | @Override 76 | public void handle(Message result) { 77 | System.out.println(result.body().getObject("value").size()); 78 | testComplete(); 79 | //never get here - lots of exceptions output instead!!! 80 | } 81 | }); 82 | } 83 | }); 84 | } 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/EvalTester.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.vertx.java.core.AsyncResult; 5 | import org.vertx.java.core.AsyncResultHandler; 6 | import org.vertx.java.core.Handler; 7 | import org.vertx.java.core.eventbus.EventBus; 8 | import org.vertx.java.core.eventbus.Message; 9 | import org.vertx.java.core.json.JsonObject; 10 | import org.vertx.testtools.TestVerticle; 11 | import org.vertx.testtools.VertxAssert; 12 | 13 | import static org.vertx.testtools.VertxAssert.*; 14 | 15 | public class EvalTester extends TestVerticle { 16 | 17 | private final String address = "test.redis.eval"; 18 | private EventBus eb; 19 | 20 | private void appReady() { 21 | super.start(); 22 | } 23 | 24 | public void start() { 25 | VertxAssert.initialize(vertx); 26 | eb = vertx.eventBus(); 27 | JsonObject config = new JsonObject(); 28 | 29 | config.putString("address", address); 30 | 31 | container.deployModule(System.getProperty("vertx.modulename"), config, 1, new AsyncResultHandler() { 32 | @Override 33 | public void handle(AsyncResult event) { 34 | appReady(); 35 | } 36 | }); 37 | } 38 | 39 | /** 40 | * Helper method to allow simple Groovy closure calls and simplified maps as json messages 41 | * @param json message 42 | * @param handler response handler 43 | */ 44 | void redis(final String json, final boolean fail, final Handler> handler) { 45 | eb.send(address, new JsonObject(json), new Handler>() { 46 | public void handle(Message reply) { 47 | if (fail) { 48 | assertEquals("error", reply.body().getString("status")); 49 | } else { 50 | assertEquals("ok", reply.body().getString("status")); 51 | } 52 | 53 | handler.handle(reply); 54 | } 55 | }); 56 | } 57 | 58 | @Test 59 | public void testEval() { 60 | 61 | String script = "\"return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}\""; 62 | 63 | redis("{\"command\": \"eval\", \"args\": [" + script + ", 2, \"key1\", \"key2\", \"first\", \"second\"]}", false, new Handler>() { 64 | @Override 65 | public void handle(Message reply) { 66 | assertEquals(4, reply.body().getArray("value").size()); 67 | testComplete(); 68 | } 69 | }); 70 | } 71 | 72 | @Test 73 | public void testEval2() { 74 | 75 | String script = "\"local items = {} for i = 1, #KEYS do items[#items + 1] = redis.call('hvals', KEYS[i]) end return items\""; 76 | 77 | redis("{\"command\": \"eval\", \"args\": [" + script + ", 1, \"a:1\"]}", false, new Handler>() { 78 | @Override 79 | public void handle(Message reply) { 80 | System.out.println(reply.body().encodePrettily()); 81 | testComplete(); 82 | } 83 | }); 84 | } 85 | 86 | @Test 87 | public void testEval3() { 88 | 89 | String script = "\"local items = {} for i = 1, #KEYS do items[#items + 1] = redis.call('hvals', KEYS[i]) end return items\""; 90 | 91 | redis("{\"command\": \"eval\", \"args\": [" + script + ", 2, \"a:1\", \"a:2\"]}", false, new Handler>() { 92 | @Override 93 | public void handle(Message reply) { 94 | System.out.println(reply.body().encodePrettily()); 95 | testComplete(); 96 | } 97 | }); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /mod/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/gradle/vertx.gradle" 2 | 3 | /* 4 | Usage: 5 | 6 | ./gradlew task_name 7 | 8 | (or gradlew.bat task_name if you have the misfortune to have to use Windows) 9 | 10 | If no task name is specified then the default task 'assemble' is run 11 | 12 | Task names are: 13 | 14 | idea - generate a skeleton IntelliJ IDEA project 15 | 16 | eclipse - generate a skeleton Eclipse IDE project 17 | 18 | assemble - builds the outputs, by default this is the module zip file. It can also include a jar file if produceJar 19 | in gradle.properties is set to true. Outputs are created in build/libs. 20 | if pullInDeps in gradle.properties is set to 'true' then the modules dependencies will be 21 | automatically pulled into a nested mods directory inside the module during the build 22 | 23 | copyMod - builds and copies the module to the local 'mods' directory so you can execute vertx runmod (etc) 24 | directly from the command line 25 | 26 | modZip - creates the module zip into build/libs 27 | 28 | clean - cleans everything up 29 | 30 | test - runs the tests. An nice html test report is created in build/reports/tests (index.html) 31 | 32 | runMod - runs the module. This is similar to executing vertx runmod from the command line except that it does 33 | not use the version of Vert.x installed and on the PATH to run it. Instead it uses the version of Vert.x 34 | that the module was compiled and tested against. 35 | 36 | runModIDEA - run the module from the project resources in IDEA. This allows you to run the module without building it 37 | first! 38 | 39 | runModEclipse - run the module from the project resources in Eclipse. This allows you to run the module without 40 | building it first! 41 | 42 | pullInDeps - pulls in all dependencies of the module into a nested module directory 43 | 44 | uploadArchives - upload the module zip file (and jar if one has been created) to Nexus. You will need to 45 | configure sonatypeUsername and sonatypePassword in ~/.gradle/gradle.properties. 46 | 47 | install - install any jars produced to the local Maven repository (.m2) 48 | 49 | */ 50 | 51 | dependencies { 52 | /* 53 | Add your module jar dependencies here 54 | E.g. 55 | compile "com.foo:foo-lib:1.0.1" - for compile time deps - this will end up in your module too! 56 | testCompile "com.foo:foo-lib:1.0.1" - for test time deps 57 | provided "com.foo:foo-lib:1.0.1" - if you DON'T want it to be packaged in the module zip 58 | */ 59 | 60 | // If you're creating Groovy compiled verticles you may need the following dependencies 61 | testCompile "org.codehaus.groovy:groovy-all:$groovyVersion" 62 | // provided "io.vertx:lang-groovy:$groovyLangModVersion@jar" 63 | 64 | } 65 | 66 | test { 67 | /* Configure which tests are included 68 | include 'org/foo/**' 69 | exclude 'org/boo/**' 70 | */ 71 | 72 | } 73 | 74 | /* 75 | If you're uploading stuff to Maven, Gradle needs to generate a POM. 76 | Please edit the details below. 77 | */ 78 | def configurePom(def pom) { 79 | pom.project { 80 | name 'mod-redis' 81 | description 'Asynchronous REDIS module for Vert.x' 82 | inceptionYear '2013' 83 | packaging produceJar == 'false' ? 'pom' : 'jar' 84 | 85 | url 'https://github.com/vert-x/mod-redis' 86 | 87 | developers { 88 | developer { 89 | id 'pmlopes' 90 | name 'Paulo Lopes' 91 | email 'pmlopes@gmail.com' 92 | } 93 | } 94 | 95 | scm { 96 | url 'https://github.com/vert-x/mod-redis' 97 | } 98 | 99 | licenses { 100 | license { 101 | name 'The Apache Software License, Version 2.0' 102 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 103 | distribution 'repo' 104 | } 105 | } 106 | 107 | properties { 108 | setProperty('project.build.sourceEncoding', 'UTF8') 109 | } 110 | } 111 | } 112 | 113 | [compileJava]*.options*.compilerArgs = ['-Xlint:all'] -------------------------------------------------------------------------------- /mod-client/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/gradle/vertx.gradle" 2 | 3 | /* 4 | Usage: 5 | 6 | ./gradlew task_name 7 | 8 | (or gradlew.bat task_name if you have the misfortune to have to use Windows) 9 | 10 | If no task name is specified then the default task 'assemble' is run 11 | 12 | Task names are: 13 | 14 | idea - generate a skeleton IntelliJ IDEA project 15 | 16 | eclipse - generate a skeleton Eclipse IDE project 17 | 18 | assemble - builds the outputs, by default this is the module zip file. It can also include a jar file if produceJar 19 | in gradle.properties is set to true. Outputs are created in build/libs. 20 | if pullInDeps in gradle.properties is set to 'true' then the modules dependencies will be 21 | automatically pulled into a nested mods directory inside the module during the build 22 | 23 | copyMod - builds and copies the module to the local 'mods' directory so you can execute vertx runmod (etc) 24 | directly from the command line 25 | 26 | modZip - creates the module zip into build/libs 27 | 28 | clean - cleans everything up 29 | 30 | test - runs the tests. An nice html test report is created in build/reports/tests (index.html) 31 | 32 | runMod - runs the module. This is similar to executing vertx runmod from the command line except that it does 33 | not use the version of Vert.x installed and on the PATH to run it. Instead it uses the version of Vert.x 34 | that the module was compiled and tested against. 35 | 36 | runModIDEA - run the module from the project resources in IDEA. This allows you to run the module without building it 37 | first! 38 | 39 | runModEclipse - run the module from the project resources in Eclipse. This allows you to run the module without 40 | building it first! 41 | 42 | pullInDeps - pulls in all dependencies of the module into a nested module directory 43 | 44 | uploadArchives - upload the module zip file (and jar if one has been created) to Nexus. You will need to 45 | configure sonatypeUsername and sonatypePassword in ~/.gradle/gradle.properties. 46 | 47 | install - install any jars produced to the local Maven repository (.m2) 48 | 49 | */ 50 | 51 | dependencies { 52 | /* 53 | Add your module jar dependencies here 54 | E.g. 55 | compile "com.foo:foo-lib:1.0.1" - for compile time deps - this will end up in your module too! 56 | testCompile "com.foo:foo-lib:1.0.1" - for test time deps 57 | provided "com.foo:foo-lib:1.0.1" - if you DON'T want it to be packaged in the module zip 58 | */ 59 | 60 | provided project(':mod') 61 | // If you're creating Groovy compiled verticles you may need the following dependencies 62 | provided "org.codehaus.groovy:groovy-all:$groovyVersion" 63 | provided "io.vertx:lang-groovy:$groovyLangModVersion@jar" 64 | 65 | } 66 | 67 | test { 68 | /* Configure which tests are included 69 | include 'org/foo/**' 70 | exclude 'org/boo/**' 71 | */ 72 | 73 | } 74 | 75 | /* 76 | If you're uploading stuff to Maven, Gradle needs to generate a POM. 77 | Please edit the details below. 78 | */ 79 | def configurePom(def pom) { 80 | pom.project { 81 | name 'mod-redis-client' 82 | description 'Asynchronous REDIS module for Vert.x' 83 | inceptionYear '2013' 84 | packaging produceJar == 'false' ? 'pom' : 'jar' 85 | 86 | url 'https://github.com/vert-x/mod-redis' 87 | 88 | developers { 89 | developer { 90 | id 'pmlopes' 91 | name 'Paulo Lopes' 92 | email 'pmlopes@gmail.com' 93 | } 94 | } 95 | 96 | scm { 97 | url 'https://github.com/vert-x/mod-redis' 98 | } 99 | 100 | licenses { 101 | license { 102 | name 'The Apache Software License, Version 2.0' 103 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 104 | distribution 'repo' 105 | } 106 | } 107 | 108 | properties { 109 | setProperty('project.build.sourceEncoding', 'UTF8') 110 | } 111 | } 112 | } 113 | 114 | [compileJava]*.options*.compilerArgs = ['-Xlint:all'] -------------------------------------------------------------------------------- /mod-client/src/main/groovy/io/vertx/groovy/redis/AbstractRedisClient.groovy: -------------------------------------------------------------------------------- 1 | package io.vertx.groovy.redis 2 | 3 | import org.vertx.groovy.core.eventbus.EventBus 4 | import org.vertx.groovy.platform.Container 5 | import org.vertx.java.core.AsyncResult 6 | 7 | class AbstractRedisClient { 8 | final EventBus eventBus 9 | final String redisAddress 10 | 11 | AbstractRedisClient(EventBus eventBus, String redisAddress) { 12 | this.eventBus = eventBus 13 | this.redisAddress = redisAddress 14 | } 15 | 16 | private static AsyncResult createAsyncResult(final boolean succeed, final String result, final Throwable cause) { 17 | return new AsyncResult() { 18 | @Override 19 | public String result() { 20 | return result; 21 | } 22 | 23 | @Override 24 | public Throwable cause() { 25 | return cause; 26 | } 27 | 28 | @Override 29 | public boolean succeeded() { 30 | return succeed; 31 | } 32 | 33 | @Override 34 | public boolean failed() { 35 | return !succeed; 36 | } 37 | }; 38 | } 39 | 40 | 41 | final void deployModule(Container container, String hostname = "localhost", int port = 6379, String encoding = "UTF-8", boolean binary = false, String auth = null, int select = 0, int instances = 1, Closure handler) { 42 | def config = [ 43 | hostname: hostname, 44 | port: port, 45 | address: redisAddress, 46 | encoding: encoding, 47 | binary: binary, 48 | auth: auth, 49 | select: select 50 | ] 51 | 52 | def mod = "io.vertx~mod-redis~1.1.5"; 53 | 54 | if (handler != null) { 55 | container.deployModule(mod, config, instances, handler) 56 | } else { 57 | container.deployModule(mod, config, instances) 58 | } 59 | } 60 | 61 | @SuppressWarnings("unchecked") 62 | final void send(RedisCommand command, Object... args) { 63 | 64 | Map json = new HashMap<>() 65 | List redisArgs = new ArrayList<>() 66 | 67 | int totalArgs = 0 68 | Closure messageHandler = null 69 | 70 | // verify if there are args 71 | if (args != null) { 72 | // verify if the last one is a Handler 73 | Object last = args[args.length - 1] 74 | totalArgs = args.length 75 | if (last instanceof Closure) { 76 | // the caller expects a result 77 | totalArgs-- 78 | messageHandler = last 79 | } 80 | } 81 | 82 | // serialize the request 83 | json.put("command", command.getCommand()) 84 | 85 | // handle special hash commands 86 | switch (command){ 87 | case [RedisCommand.MSET, RedisCommand.MSETNX, RedisCommand.HMSET, RedisCommand.ZADD]: 88 | if (totalArgs == 2 && args[1] instanceof Map) { 89 | // there are only 2 arguments and the last is a json object, convert the hash into a redis command 90 | redisArgs.add(args[0]) 91 | args[1].each() {key, value -> 92 | redisArgs.add(key) 93 | redisArgs.add(value) 94 | } 95 | 96 | // remove these 2 since they are already added to the args array 97 | totalArgs = 0 98 | } 99 | break; 100 | } 101 | 102 | // serialize arguments 103 | for (int i = 0; i < totalArgs; i++) { 104 | redisArgs.add(args[i]) 105 | } 106 | 107 | json.put("args", redisArgs) 108 | 109 | if (messageHandler != null) { 110 | eventBus.send(redisAddress, json, messageHandler) 111 | } else { 112 | eventBus.send(redisAddress, json) 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/Reply.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.vertx.java.core.buffer.Buffer; 4 | import org.vertx.java.core.json.JsonArray; 5 | import org.vertx.java.core.json.JsonObject; 6 | 7 | public final class Reply { 8 | 9 | private final byte type; 10 | private final Object data; 11 | 12 | public Reply(byte type, Object data) { 13 | this.type = type; 14 | this.data = data; 15 | } 16 | 17 | public Reply(byte type, int size) { 18 | this.type = type; 19 | this.data = new Reply[size]; 20 | } 21 | 22 | public Reply(char type, Object data) { 23 | this.type = (byte) type; 24 | this.data = data; 25 | } 26 | 27 | public Reply(char type, int size) { 28 | this.type = (byte) type; 29 | this.data = new Reply[size]; 30 | } 31 | 32 | void set(int pos, Reply reply) { 33 | ((Reply[]) data)[pos] = reply; 34 | } 35 | 36 | public boolean is(byte b) { 37 | return type == b; 38 | } 39 | 40 | public boolean is(char b) { 41 | return type == (byte) b; 42 | } 43 | 44 | /** 45 | * Return the type of instance of this Reply. Useful to avoid checks against instanceof 46 | * @return enum 47 | */ 48 | byte type() { 49 | return type; 50 | } 51 | 52 | public Object data() { 53 | return data; 54 | } 55 | 56 | public String toString(String encoding) { 57 | if (data == null) return null; 58 | if (data instanceof String) { 59 | return (String) data; 60 | } 61 | if (data instanceof Buffer) { 62 | return ((Buffer) data).toString(encoding); 63 | } 64 | return data.toString(); 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | if (data == null) return null; 70 | if (data instanceof String) { 71 | return (String) data; 72 | } 73 | return data.toString(); 74 | } 75 | 76 | public Number toNumber() { 77 | if (data == null) return null; 78 | return (Number) data; 79 | } 80 | 81 | public JsonArray toJsonArray() { 82 | return toJsonArray("UTF-8"); 83 | } 84 | 85 | public JsonArray toJsonArray(String encoding) { 86 | final JsonArray multi = new JsonArray(); 87 | 88 | for (Reply r : (Reply[]) data) { 89 | switch (r.type()) { 90 | case '$': // Bulk 91 | multi.addString(r.toString(encoding)); 92 | break; 93 | case ':': // Integer 94 | multi.addNumber(r.toNumber()); 95 | break; 96 | case '*': // Multi 97 | multi.addArray(r.toJsonArray()); 98 | break; 99 | default: 100 | throw new RuntimeException("Unknown sub message type in multi: " + r.type()); 101 | } 102 | } 103 | 104 | return multi; 105 | } 106 | 107 | public JsonObject toJsonObject() { 108 | return toJsonObject("UTF-8"); 109 | } 110 | 111 | public JsonObject toJsonObject(String encoding) { 112 | final JsonObject multi = new JsonObject(); 113 | 114 | for (int i = 0; i < ((Reply[]) data).length; i+=2) { 115 | if (((Reply[]) data)[i].type() != '$') { 116 | throw new RuntimeException("Expected String as key type in multi: " + ((Reply[]) data)[i].type()); 117 | } 118 | 119 | Reply brKey = ((Reply[]) data)[i]; 120 | Reply brValue = ((Reply[]) data)[i+1]; 121 | 122 | switch (brValue.type()) { 123 | case '$': // Bulk 124 | multi.putString(brKey.toString(encoding), brValue.toString(encoding)); 125 | break; 126 | case ':': // Integer 127 | multi.putNumber(brKey.toString(encoding), brValue.toNumber()); 128 | break; 129 | case '*': // Multi 130 | multi.putArray(brKey.toString(encoding), brValue.toJsonArray()); 131 | break; 132 | default: 133 | throw new RuntimeException("Unknown sub message type in multi: " + ((Reply[]) data)[i+1].type()); 134 | } 135 | 136 | } 137 | return multi; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /mod-client/src/main/java/io/vertx/java/redis/RedisCommand.java: -------------------------------------------------------------------------------- 1 | package io.vertx.java.redis; 2 | 3 | public enum RedisCommand { 4 | HMGET("HMGET"), 5 | HMSET("HMSET"), 6 | ZREVRANK("ZREVRANK"), 7 | PEXPIREAT("PEXPIREAT"), 8 | TTL("TTL"), 9 | SCRIPT_EXISTS("SCRIPT EXISTS"), 10 | SINTERSTORE("SINTERSTORE"), 11 | LASTSAVE("LASTSAVE"), 12 | STRLEN("STRLEN"), 13 | SMOVE("SMOVE"), 14 | UNWATCH("UNWATCH"), 15 | TYPE("TYPE"), 16 | SADD("SADD"), 17 | INCR("INCR"), 18 | BITCOUNT("BITCOUNT"), 19 | LSET("LSET"), 20 | MONITOR("MONITOR"), 21 | GET("GET"), 22 | DEBUG_SEGFAULT("DEBUG SEGFAULT"), 23 | RPUSH("RPUSH"), 24 | LRANGE("LRANGE"), 25 | HDEL("HDEL"), 26 | PFMERGE("PFMERGE"), 27 | SELECT("SELECT"), 28 | BITPOS("BITPOS"), 29 | PUBSUB("PUBSUB"), 30 | LINSERT("LINSERT"), 31 | PFADD("PFADD"), 32 | BRPOPLPUSH("BRPOPLPUSH"), 33 | LTRIM("LTRIM"), 34 | MSET("MSET"), 35 | RESTORE("RESTORE"), 36 | SINTER("SINTER"), 37 | BRPOP("BRPOP"), 38 | WATCH("WATCH"), 39 | CLIENT_GETNAME("CLIENT GETNAME"), 40 | CONFIG_GET("CONFIG GET"), 41 | SMEMBERS("SMEMBERS"), 42 | SETNX("SETNX"), 43 | ZREVRANGEBYSCORE("ZREVRANGEBYSCORE"), 44 | INCRBYFLOAT("INCRBYFLOAT"), 45 | SPOP("SPOP"), 46 | HLEN("HLEN"), 47 | SLAVEOF("SLAVEOF"), 48 | PSETEX("PSETEX"), 49 | EXPIRE("EXPIRE"), 50 | DECRBY("DECRBY"), 51 | MSETNX("MSETNX"), 52 | PING("PING"), 53 | DISCARD("DISCARD"), 54 | ZUNIONSTORE("ZUNIONSTORE"), 55 | EVAL("EVAL"), 56 | ZRANGEBYLEX("ZRANGEBYLEX"), 57 | MIGRATE("MIGRATE"), 58 | FLUSHDB("FLUSHDB"), 59 | LLEN("LLEN"), 60 | SHUTDOWN("SHUTDOWN"), 61 | PTTL("PTTL"), 62 | HGETALL("HGETALL"), 63 | CONFIG_REWRITE("CONFIG REWRITE"), 64 | ZREM("ZREM"), 65 | BITOP("BITOP"), 66 | SCRIPT_KILL("SCRIPT KILL"), 67 | SUNION("SUNION"), 68 | RENAME("RENAME"), 69 | RPOPLPUSH("RPOPLPUSH"), 70 | DBSIZE("DBSIZE"), 71 | APPEND("APPEND"), 72 | DEL("DEL"), 73 | RANDOMKEY("RANDOMKEY"), 74 | CLIENT_KILL("CLIENT KILL"), 75 | HGET("HGET"), 76 | SREM("SREM"), 77 | SUBSCRIBE("SUBSCRIBE"), 78 | ZSCAN("ZSCAN"), 79 | MULTI("MULTI"), 80 | HSET("HSET"), 81 | RPUSHX("RPUSHX"), 82 | SISMEMBER("SISMEMBER"), 83 | SETBIT("SETBIT"), 84 | QUIT("QUIT"), 85 | TIME("TIME"), 86 | PUNSUBSCRIBE("PUNSUBSCRIBE"), 87 | SLOWLOG("SLOWLOG"), 88 | ZINCRBY("ZINCRBY"), 89 | SCARD("SCARD"), 90 | AUTH("AUTH"), 91 | OBJECT("OBJECT"), 92 | SDIFFSTORE("SDIFFSTORE"), 93 | LREM("LREM"), 94 | SCAN("SCAN"), 95 | SCRIPT_LOAD("SCRIPT LOAD"), 96 | DUMP("DUMP"), 97 | UNSUBSCRIBE("UNSUBSCRIBE"), 98 | ZINTERSTORE("ZINTERSTORE"), 99 | ZRANGEBYSCORE("ZRANGEBYSCORE"), 100 | MGET("MGET"), 101 | EXPIREAT("EXPIREAT"), 102 | ZREMRANGEBYSCORE("ZREMRANGEBYSCORE"), 103 | ZRANK("ZRANK"), 104 | EXISTS("EXISTS"), 105 | ZRANGE("ZRANGE"), 106 | GETRANGE("GETRANGE"), 107 | SETEX("SETEX"), 108 | ZCARD("ZCARD"), 109 | CONFIG_RESETSTAT("CONFIG RESETSTAT"), 110 | ZREVRANGE("ZREVRANGE"), 111 | BLPOP("BLPOP"), 112 | ZADD("ZADD"), 113 | SDIFF("SDIFF"), 114 | HINCRBYFLOAT("HINCRBYFLOAT"), 115 | HEXISTS("HEXISTS"), 116 | BGREWRITEAOF("BGREWRITEAOF"), 117 | SYNC("SYNC"), 118 | ZLEXCOUNT("ZLEXCOUNT"), 119 | GETSET("GETSET"), 120 | FLUSHALL("FLUSHALL"), 121 | RENAMENX("RENAMENX"), 122 | SUNIONSTORE("SUNIONSTORE"), 123 | HSCAN("HSCAN"), 124 | SORT("SORT"), 125 | ZSCORE("ZSCORE"), 126 | SET("SET"), 127 | SAVE("SAVE"), 128 | EXEC("EXEC"), 129 | HINCRBY("HINCRBY"), 130 | HKEYS("HKEYS"), 131 | SRANDMEMBER("SRANDMEMBER"), 132 | SSCAN("SSCAN"), 133 | LINDEX("LINDEX"), 134 | INCRBY("INCRBY"), 135 | INFO("INFO"), 136 | ZREMRANGEBYRANK("ZREMRANGEBYRANK"), 137 | ZCOUNT("ZCOUNT"), 138 | SETRANGE("SETRANGE"), 139 | LPOP("LPOP"), 140 | PFCOUNT("PFCOUNT"), 141 | PSUBSCRIBE("PSUBSCRIBE"), 142 | ECHO("ECHO"), 143 | BGSAVE("BGSAVE"), 144 | EVALSHA("EVALSHA"), 145 | LPUSH("LPUSH"), 146 | PERSIST("PERSIST"), 147 | PEXPIRE("PEXPIRE"), 148 | CLIENT_PAUSE("CLIENT PAUSE"), 149 | RPOP("RPOP"), 150 | MOVE("MOVE"), 151 | LPUSHX("LPUSHX"), 152 | DECR("DECR"), 153 | HVALS("HVALS"), 154 | CONFIG_SET("CONFIG SET"), 155 | KEYS("KEYS"), 156 | HSETNX("HSETNX"), 157 | GETBIT("GETBIT"), 158 | CLIENT_LIST("CLIENT LIST"), 159 | CLIENT_SETNAME("CLIENT SETNAME"), 160 | PUBLISH("PUBLISH"), 161 | ZREMRANGEBYLEX("ZREMRANGEBYLEX"), 162 | SCRIPT_FLUSH("SCRIPT FLUSH"), 163 | DEBUG_OBJECT("DEBUG OBJECT"), 164 | ; 165 | 166 | private final String command; 167 | 168 | RedisCommand(String command) 169 | { 170 | this.command = command; 171 | } 172 | 173 | public String getCommand() 174 | { 175 | return command; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /mod-client/src/test/groovy/io/vertx/redis/Generate.groovy: -------------------------------------------------------------------------------- 1 | package io.vertx.redis 2 | 3 | import groovy.json.JsonSlurper 4 | import groovy.text.SimpleTemplateEngine 5 | 6 | class Generate { 7 | 8 | public static void main(String[] args) { 9 | def slurper = new JsonSlurper() 10 | def result = slurper.parse(new InputStreamReader(new URL('http://redis.io/commands.json').openStream())) 11 | 12 | generateJava(result) 13 | generateGroovy(result) 14 | generateJS(result) 15 | } 16 | 17 | static void generateJava(commands) { 18 | def engine = new SimpleTemplateEngine() 19 | 20 | def text = '''package io.vertx.java.redis; 21 | 22 | import org.vertx.java.core.eventbus.EventBus; 23 | 24 | public class RedisClient extends AbstractRedisClient { 25 | 26 | public RedisClient(EventBus eventBus, String redisAddress) { 27 | super(eventBus, redisAddress); 28 | } 29 | 30 | <%for (cmd in json) {%> /** 31 | * <% print cmd.value.summary %> 32 | * @since <% print cmd.value.since %> 33 | */ 34 | public void <% print cmd.key.toLowerCase().replace(' ', '_') %>(Object... args) {send("<% print cmd.key %>", args);} 35 | 36 | <%}%> 37 | } 38 | ''' 39 | engine.createTemplate(text).make([json: commands]).writeTo(new OutputStreamWriter(new FileOutputStream("mod-client/src/main/java/io/vertx/java/redis/RedisClient.java"))) 40 | } 41 | 42 | static void generateGroovy(commands) { 43 | def engine = new SimpleTemplateEngine() 44 | 45 | def text = '''package io.vertx.groovy.redis; 46 | 47 | import org.vertx.groovy.core.eventbus.EventBus; 48 | 49 | public class RedisClient extends AbstractRedisClient { 50 | 51 | public RedisClient(EventBus eventBus, String redisAddress) { 52 | super(eventBus, redisAddress); 53 | } 54 | 55 | <%for (cmd in json) {%> /** 56 | * <% print cmd.value.summary %> 57 | * @since <% print cmd.value.since %> 58 | */ 59 | public void <% print cmd.key.toLowerCase().replace(' ', '_') %>(Object... args) {send("<% print cmd.key %>", args);} 60 | 61 | <%}%> 62 | } 63 | ''' 64 | engine.createTemplate(text).make([json: commands]).writeTo(new OutputStreamWriter(new FileOutputStream("mod-client/src/main/groovy/io/vertx/groovy/redis/RedisClient.java"))) 65 | } 66 | 67 | static void generateJS(commands) { 68 | def engine = new SimpleTemplateEngine() 69 | 70 | def text = '''var container = require("vertx/container"); 71 | var vertx = require("vertx"); 72 | 73 | module.exports = function (redisAddress) { 74 | this.eventBus = vertx.eventBus; 75 | this.redisAddress = redisAddress; 76 | }; 77 | 78 | module.exports.prototype.deployModule = function (options, instances, handler) { 79 | var config = { 80 | hostname: options.hostname || "localhost", 81 | port: options.port || 6379, 82 | address: this.redisAddress, 83 | encoding: options.encoding || "UTF-8", 84 | binary: options.binary || false, 85 | auth: options.auth || null 86 | }; 87 | 88 | if (handler) { 89 | container.deployModule("io.vertx~mod-redis~1.1.5", config, instances, handler); 90 | } else { 91 | container.deployModule("io.vertx~mod-redis~1.1.5", instances, config); 92 | } 93 | }; 94 | 95 | module.exports.prototype.send = function(command, args) { 96 | var json = {command: command, args: []}; 97 | var totalArgs = 0; 98 | var messageHandler = null; 99 | 100 | // verify if there are args 101 | if (args != null) { 102 | // verify if the last one is a Handler 103 | var last = args[args.length - 1]; 104 | totalArgs = args.length; 105 | if (last instanceof Function) { 106 | // the caller expects a result 107 | totalArgs--; 108 | messageHandler = last; 109 | } 110 | } 111 | 112 | // serialize arguments 113 | for (var i = 0; i < totalArgs; i++) { 114 | json.args.push(args[i]); 115 | } 116 | 117 | if (messageHandler) { 118 | this.eventBus.send(this.redisAddress, json, messageHandler); 119 | } else { 120 | this.eventBus.send(this.redisAddress, json); 121 | } 122 | }; 123 | 124 | <%for (cmd in json) {%>/** 125 | * <% print cmd.value.summary %> 126 | * @since <% print cmd.value.since %> 127 | */ 128 | module.exports.prototype.<% print cmd.key.toLowerCase().replace(' ', '_') %> = function() {this.send("<% print cmd.key %>", arguments);}; 129 | 130 | <%}%> 131 | ''' 132 | engine.createTemplate(text).make([json: commands]).writeTo(new OutputStreamWriter(new FileOutputStream("mod-client/src/main/resources/redisClient.js"))) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /mod-client/src/main/groovy/io/vertx/groovy/redis/RedisCommand.groovy: -------------------------------------------------------------------------------- 1 | package io.vertx.groovy.redis; 2 | 3 | public enum RedisCommand { 4 | HMGET("HMGET"), 5 | HMSET("HMSET"), 6 | ZREVRANK("ZREVRANK"), 7 | PEXPIREAT("PEXPIREAT"), 8 | TTL("TTL"), 9 | SCRIPT_EXISTS("SCRIPT EXISTS"), 10 | SINTERSTORE("SINTERSTORE"), 11 | LASTSAVE("LASTSAVE"), 12 | STRLEN("STRLEN"), 13 | SMOVE("SMOVE"), 14 | UNWATCH("UNWATCH"), 15 | TYPE("TYPE"), 16 | SADD("SADD"), 17 | INCR("INCR"), 18 | BITCOUNT("BITCOUNT"), 19 | LSET("LSET"), 20 | MONITOR("MONITOR"), 21 | GET("GET"), 22 | DEBUG_SEGFAULT("DEBUG SEGFAULT"), 23 | RPUSH("RPUSH"), 24 | LRANGE("LRANGE"), 25 | HDEL("HDEL"), 26 | PFMERGE("PFMERGE"), 27 | SELECT("SELECT"), 28 | BITPOS("BITPOS"), 29 | PUBSUB("PUBSUB"), 30 | LINSERT("LINSERT"), 31 | PFADD("PFADD"), 32 | BRPOPLPUSH("BRPOPLPUSH"), 33 | LTRIM("LTRIM"), 34 | MSET("MSET"), 35 | RESTORE("RESTORE"), 36 | SINTER("SINTER"), 37 | BRPOP("BRPOP"), 38 | WATCH("WATCH"), 39 | CLIENT_GETNAME("CLIENT GETNAME"), 40 | CONFIG_GET("CONFIG GET"), 41 | SMEMBERS("SMEMBERS"), 42 | SETNX("SETNX"), 43 | ZREVRANGEBYSCORE("ZREVRANGEBYSCORE"), 44 | INCRBYFLOAT("INCRBYFLOAT"), 45 | SPOP("SPOP"), 46 | HLEN("HLEN"), 47 | SLAVEOF("SLAVEOF"), 48 | PSETEX("PSETEX"), 49 | EXPIRE("EXPIRE"), 50 | DECRBY("DECRBY"), 51 | MSETNX("MSETNX"), 52 | PING("PING"), 53 | DISCARD("DISCARD"), 54 | ZUNIONSTORE("ZUNIONSTORE"), 55 | EVAL("EVAL"), 56 | ZRANGEBYLEX("ZRANGEBYLEX"), 57 | MIGRATE("MIGRATE"), 58 | FLUSHDB("FLUSHDB"), 59 | LLEN("LLEN"), 60 | SHUTDOWN("SHUTDOWN"), 61 | PTTL("PTTL"), 62 | HGETALL("HGETALL"), 63 | CONFIG_REWRITE("CONFIG REWRITE"), 64 | ZREM("ZREM"), 65 | BITOP("BITOP"), 66 | SCRIPT_KILL("SCRIPT KILL"), 67 | SUNION("SUNION"), 68 | RENAME("RENAME"), 69 | RPOPLPUSH("RPOPLPUSH"), 70 | DBSIZE("DBSIZE"), 71 | APPEND("APPEND"), 72 | DEL("DEL"), 73 | RANDOMKEY("RANDOMKEY"), 74 | CLIENT_KILL("CLIENT KILL"), 75 | HGET("HGET"), 76 | SREM("SREM"), 77 | SUBSCRIBE("SUBSCRIBE"), 78 | ZSCAN("ZSCAN"), 79 | MULTI("MULTI"), 80 | HSET("HSET"), 81 | RPUSHX("RPUSHX"), 82 | SISMEMBER("SISMEMBER"), 83 | SETBIT("SETBIT"), 84 | QUIT("QUIT"), 85 | TIME("TIME"), 86 | PUNSUBSCRIBE("PUNSUBSCRIBE"), 87 | SLOWLOG("SLOWLOG"), 88 | ZINCRBY("ZINCRBY"), 89 | SCARD("SCARD"), 90 | AUTH("AUTH"), 91 | OBJECT("OBJECT"), 92 | SDIFFSTORE("SDIFFSTORE"), 93 | LREM("LREM"), 94 | SCAN("SCAN"), 95 | SCRIPT_LOAD("SCRIPT LOAD"), 96 | DUMP("DUMP"), 97 | UNSUBSCRIBE("UNSUBSCRIBE"), 98 | ZINTERSTORE("ZINTERSTORE"), 99 | ZRANGEBYSCORE("ZRANGEBYSCORE"), 100 | MGET("MGET"), 101 | EXPIREAT("EXPIREAT"), 102 | ZREMRANGEBYSCORE("ZREMRANGEBYSCORE"), 103 | ZRANK("ZRANK"), 104 | EXISTS("EXISTS"), 105 | ZRANGE("ZRANGE"), 106 | GETRANGE("GETRANGE"), 107 | SETEX("SETEX"), 108 | ZCARD("ZCARD"), 109 | CONFIG_RESETSTAT("CONFIG RESETSTAT"), 110 | ZREVRANGE("ZREVRANGE"), 111 | BLPOP("BLPOP"), 112 | ZADD("ZADD"), 113 | SDIFF("SDIFF"), 114 | HINCRBYFLOAT("HINCRBYFLOAT"), 115 | HEXISTS("HEXISTS"), 116 | BGREWRITEAOF("BGREWRITEAOF"), 117 | SYNC("SYNC"), 118 | ZLEXCOUNT("ZLEXCOUNT"), 119 | GETSET("GETSET"), 120 | FLUSHALL("FLUSHALL"), 121 | RENAMENX("RENAMENX"), 122 | SUNIONSTORE("SUNIONSTORE"), 123 | HSCAN("HSCAN"), 124 | SORT("SORT"), 125 | ZSCORE("ZSCORE"), 126 | SET("SET"), 127 | SAVE("SAVE"), 128 | EXEC("EXEC"), 129 | HINCRBY("HINCRBY"), 130 | HKEYS("HKEYS"), 131 | SRANDMEMBER("SRANDMEMBER"), 132 | SSCAN("SSCAN"), 133 | LINDEX("LINDEX"), 134 | INCRBY("INCRBY"), 135 | INFO("INFO"), 136 | ZREMRANGEBYRANK("ZREMRANGEBYRANK"), 137 | ZCOUNT("ZCOUNT"), 138 | SETRANGE("SETRANGE"), 139 | LPOP("LPOP"), 140 | PFCOUNT("PFCOUNT"), 141 | PSUBSCRIBE("PSUBSCRIBE"), 142 | ECHO("ECHO"), 143 | BGSAVE("BGSAVE"), 144 | EVALSHA("EVALSHA"), 145 | LPUSH("LPUSH"), 146 | PERSIST("PERSIST"), 147 | PEXPIRE("PEXPIRE"), 148 | CLIENT_PAUSE("CLIENT PAUSE"), 149 | RPOP("RPOP"), 150 | MOVE("MOVE"), 151 | LPUSHX("LPUSHX"), 152 | DECR("DECR"), 153 | HVALS("HVALS"), 154 | CONFIG_SET("CONFIG SET"), 155 | KEYS("KEYS"), 156 | HSETNX("HSETNX"), 157 | GETBIT("GETBIT"), 158 | CLIENT_LIST("CLIENT LIST"), 159 | CLIENT_SETNAME("CLIENT SETNAME"), 160 | PUBLISH("PUBLISH"), 161 | ZREMRANGEBYLEX("ZREMRANGEBYLEX"), 162 | SCRIPT_FLUSH("SCRIPT FLUSH"), 163 | DEBUG_OBJECT("DEBUG OBJECT"); 164 | 165 | private final String command; 166 | 167 | RedisCommand(String command) 168 | { 169 | this.command = command; 170 | } 171 | 172 | public String getCommand() 173 | { 174 | return command; 175 | } 176 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="-Dfile.encoding=UTF-8" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain --daemon "$@" 165 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/LoadTester.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.vertx.java.core.AsyncResult; 5 | import org.vertx.java.core.AsyncResultHandler; 6 | import org.vertx.java.core.Handler; 7 | import org.vertx.java.core.eventbus.EventBus; 8 | import org.vertx.java.core.eventbus.Message; 9 | import org.vertx.java.core.json.JsonObject; 10 | import org.vertx.testtools.TestVerticle; 11 | import org.vertx.testtools.VertxAssert; 12 | 13 | import java.util.concurrent.atomic.AtomicInteger; 14 | 15 | import static org.vertx.testtools.VertxAssert.*; 16 | 17 | public class LoadTester extends TestVerticle { 18 | 19 | private final String address = "test.redis.load"; 20 | private EventBus eb; 21 | 22 | private void appReady() { 23 | super.start(); 24 | } 25 | 26 | public void start() { 27 | VertxAssert.initialize(vertx); 28 | eb = vertx.eventBus(); 29 | JsonObject config = new JsonObject(); 30 | 31 | config.putString("address", address); 32 | 33 | container.deployModule(System.getProperty("vertx.modulename"), config, 1, new AsyncResultHandler() { 34 | @Override 35 | public void handle(AsyncResult event) { 36 | appReady(); 37 | } 38 | }); 39 | } 40 | 41 | /** 42 | * Helper method to allow simple Groovy closure calls and simplified maps as json messages 43 | * @param json message 44 | * @param handler response handler 45 | */ 46 | void redis(final String json, final Handler> handler) { 47 | eb.send(address, new JsonObject(json), handler); 48 | } 49 | 50 | void query(String json, final Handler handler) { 51 | eb.send(address, new JsonObject(json), new Handler>() { 52 | @Override 53 | public void handle(Message reply) { 54 | int queries = counter.decrementAndGet(); 55 | 56 | String result = reply.body().getString("status"); 57 | if ("error".equals(result)) { 58 | fail(reply.body().getString("message")); 59 | } else { 60 | assertEquals("ok", result); 61 | handler.handle(reply.body().getField("value")); 62 | } 63 | 64 | if (queries == 0) { 65 | testComplete(); 66 | } 67 | } 68 | }); 69 | } 70 | 71 | final AtomicInteger counter = new AtomicInteger(); 72 | 73 | @Test 74 | public void testLoad() { 75 | 76 | // setup 77 | final Handler> okHandler = new Handler>() { 78 | @Override 79 | public void handle(Message reply) { 80 | String result = reply.body().getString("status"); 81 | if ("error".equals(result)) { 82 | fail(reply.body().getString("message")); 83 | } else { 84 | assertEquals("ok", result); 85 | } 86 | } 87 | }; 88 | 89 | redis("{\"command\":\"rpush\",\"args\":[\"list0\",0,10,12,5,3,4,8,9,13,1,6,4]}", okHandler); 90 | redis("{\"command\":\"sadd\",\"args\":[\"set0\",\"joe\",\"mark\",\"drew\",\"paul\",\"wario\"]}", okHandler); 91 | redis("{\"command\":\"sadd\",\"args\":[\"set1\",\"mark\",\"drew\",\"wario\",\"marie\"]}", okHandler); 92 | redis("{\"command\":\"set\",\"args\":[\"string0\",\"15\"]}", okHandler); 93 | redis("{\"command\":\"set\",\"args\":[\"string1\",\"7\"]}", okHandler); 94 | 95 | int repetitions = 1024; 96 | counter.set(repetitions * 7); 97 | 98 | // test 99 | for (int i = 0; i < repetitions; i++) { 100 | query("{\"command\":\"smembers\",\"args\":[\"set0\"]}", new Handler() { 101 | @Override 102 | public void handle(Object json) { 103 | //System.out.println("smembers: " + json); 104 | } 105 | }); 106 | 107 | query("{\"command\":\"lrange\",\"args\":[\"list0\",0,-1]}", new Handler() { 108 | @Override 109 | public void handle(Object json) { 110 | //System.out.println("lrange: " + json); 111 | 112 | query("{\"command\":\"mget\",\"args\":[\"string0\",\"string1\"]}", new Handler() { 113 | @Override 114 | public void handle(Object json) { 115 | //System.out.println("mget: " + json); 116 | 117 | query("{\"command\":\"scard\",\"args\":[\"set1\"]}", new Handler() { 118 | @Override 119 | public void handle(Object json) { 120 | //System.out.println("mget: " + json); 121 | } 122 | }); 123 | } 124 | }); 125 | } 126 | }); 127 | 128 | query("{\"command\":\"lrange\",\"args\":[\"list0\",1,-3]}", new Handler() { 129 | @Override 130 | public void handle(Object json) { 131 | //System.out.println("lrange: " + json); 132 | 133 | query("{\"command\":\"scard\",\"args\":[\"set1\"]}", new Handler() { 134 | @Override 135 | public void handle(Object json) { 136 | //System.out.println("scard: " + json); 137 | } 138 | }); 139 | } 140 | }); 141 | 142 | query("{\"command\":\"lrange\",\"args\":[\"list0\",0,-1]}", new Handler() { 143 | @Override 144 | public void handle(Object json) { 145 | //System.out.println("lrange: " + json); 146 | } 147 | }); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /mod/src/test/java/io/vertx/redis/RedisClientTester.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.junit.Test; 4 | import org.vertx.java.core.AsyncResult; 5 | import org.vertx.java.core.AsyncResultHandler; 6 | import org.vertx.java.core.Handler; 7 | import org.vertx.java.core.eventbus.EventBus; 8 | import org.vertx.java.core.eventbus.Message; 9 | import org.vertx.java.core.json.JsonArray; 10 | import org.vertx.java.core.json.JsonObject; 11 | import org.vertx.testtools.TestVerticle; 12 | import org.vertx.testtools.VertxAssert; 13 | 14 | import java.util.List; 15 | import java.util.UUID; 16 | 17 | import static org.vertx.testtools.VertxAssert.*; 18 | import static org.vertx.testtools.VertxAssert.assertEquals; 19 | 20 | public class RedisClientTester extends TestVerticle { 21 | 22 | private final String address = "test.redis.client"; 23 | private EventBus eb; 24 | 25 | private void appReady() { 26 | super.start(); 27 | } 28 | 29 | public void start() { 30 | VertxAssert.initialize(vertx); 31 | eb = vertx.eventBus(); 32 | JsonObject config = new JsonObject(); 33 | 34 | config.putString("address", address); 35 | config.putString("host", "localhost"); 36 | config.putNumber("port", 6379); 37 | config.putString("encoding", "ISO-8859-1"); 38 | 39 | container.deployModule(System.getProperty("vertx.modulename"), config, 1, new AsyncResultHandler() { 40 | @Override 41 | public void handle(AsyncResult event) { 42 | appReady(); 43 | } 44 | }); 45 | } 46 | 47 | /** 48 | * Helper method to allow simple Groovy closure calls and simplified maps as json messages 49 | * @param json message 50 | * @param handler response handler 51 | */ 52 | void redis(final JsonObject json, final boolean fail, final Handler> handler) { 53 | eb.send(address, json, new Handler>() { 54 | public void handle(Message reply) { 55 | if (fail) { 56 | assertEquals("error", reply.body().getString("status")); 57 | } else { 58 | assertEquals("ok", reply.body().getString("status")); 59 | } 60 | 61 | handler.handle(reply); 62 | } 63 | }); 64 | } 65 | 66 | private static String makeKey() { 67 | return UUID.randomUUID().toString(); 68 | } 69 | 70 | private static void assertNumberValue(Number expected, Message value) { 71 | assertEquals(expected, value.body().getNumber("value")); 72 | } 73 | 74 | private static void assertStringValue(String expected, Message value) { 75 | assertEquals(expected, value.body().getString("value")); 76 | } 77 | 78 | private static void assertNullValue(Message value) { 79 | assertEquals(null, value.body().getField("value")); 80 | } 81 | 82 | private static void assertNotNullValue(Message value) { 83 | assertNotSame(null, value.body().getField("value")); 84 | } 85 | 86 | void assertArrayValue(List expected, Message value) { 87 | JsonArray array = value.body().getArray("value"); 88 | assertNotNull(array); 89 | assertEquals(expected.size(), array.size()); 90 | 91 | for (int i = 0; i < array.size(); i++) { 92 | if (expected.get(i) == null) { 93 | assertNull(array.get(i)); 94 | } else { 95 | assertEquals(expected.get(i), array.get(i)); 96 | } 97 | } 98 | } 99 | 100 | private static void assertUnorderedArrayValue(List expected, Message value) { 101 | JsonArray array = value.body().getArray("value"); 102 | assertNotNull(array); 103 | assertEquals(expected.size(), array.size()); 104 | 105 | for (int i = 0; i < array.size(); i++) { 106 | boolean found = false; 107 | for (int j = 0; j < expected.size(); j++) { 108 | if (expected.get(j) == null && array.get(i) == null) { 109 | found = true; 110 | expected.remove(j); 111 | break; 112 | } 113 | if (expected.get(j).equals(array.get(i))) { 114 | found = true; 115 | expected.remove(j); 116 | break; 117 | } 118 | } 119 | 120 | assertTrue("Expected one of: <" + expected + "> but got: <" + array.get(i) + ">", found); 121 | } 122 | } 123 | 124 | private static JsonObject json(String command, Object... args) { 125 | JsonObject json = new JsonObject(); 126 | json.putString("command", command); 127 | if (args != null) { 128 | JsonArray jsonArgs = new JsonArray(); 129 | for (Object o : args) { 130 | jsonArgs.add(o); 131 | } 132 | json.putArray("args", jsonArgs); 133 | } 134 | return json; 135 | } 136 | 137 | @Test 138 | public void testGet() { 139 | final String nonexisting = makeKey(); 140 | final String mykey = makeKey(); 141 | 142 | redis(json("get", nonexisting), false, new Handler>() { 143 | @Override 144 | public void handle(Message reply) { 145 | assertNullValue(reply); 146 | 147 | redis(json("set", mykey, "Hello"), false, new Handler>() { 148 | @Override 149 | public void handle(Message reply) { 150 | 151 | redis(json("get", mykey), false, new Handler>() { 152 | @Override 153 | public void handle(Message reply) { 154 | 155 | assertStringValue("Hello", reply); 156 | testComplete(); 157 | } 158 | }); 159 | } 160 | }); 161 | } 162 | }); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/ReplyParser.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.redis.impl.ReplyHandler; 4 | import org.vertx.java.core.Handler; 5 | import org.vertx.java.core.buffer.Buffer; 6 | 7 | public class ReplyParser implements Handler { 8 | 9 | private Buffer _buffer; 10 | private int _offset; 11 | private final String _encoding = "utf-8"; 12 | 13 | private final ReplyHandler client; 14 | 15 | public ReplyParser(ReplyHandler client) { 16 | this.client = client; 17 | } 18 | 19 | 20 | private Reply parseResult(byte type) throws ArrayIndexOutOfBoundsException { 21 | int start, end, offset; 22 | int packetSize; 23 | 24 | if (type == '+' || type == '-') { 25 | // up to the delimiter 26 | end = packetEndOffset() - 1; 27 | start = _offset; 28 | 29 | // include the delimiter 30 | _offset = end + 2; 31 | 32 | if (end > _buffer.length()) { 33 | _offset = start; 34 | throw new ArrayIndexOutOfBoundsException("Wait for more data."); 35 | } 36 | 37 | if (type == '+') { 38 | return new Reply(type, _buffer.getString(start, end, _encoding)); 39 | } else { 40 | return new Reply(type, _buffer.getString(start, end, _encoding)); 41 | } 42 | } else if (type == ':') { 43 | // up to the delimiter 44 | end = packetEndOffset() - 1; 45 | start = _offset; 46 | 47 | // include the delimiter 48 | _offset = end + 2; 49 | 50 | if (end > _buffer.length()) { 51 | _offset = start; 52 | throw new ArrayIndexOutOfBoundsException("Wait for more data."); 53 | } 54 | 55 | // return the coerced numeric value 56 | return new Reply(type, Long.parseLong(_buffer.getString(start, end))); 57 | } else if (type == '$') { 58 | // set a rewind point, as the packet could be larger than the 59 | // buffer in memory 60 | offset = _offset - 1; 61 | 62 | packetSize = parsePacketSize(); 63 | 64 | // packets with a size of -1 are considered null 65 | if (packetSize == -1) { 66 | return new Reply(type, null); 67 | } 68 | 69 | end = _offset + packetSize; 70 | start = _offset; 71 | 72 | // set the offset to after the delimiter 73 | _offset = end + 2; 74 | 75 | if (end > _buffer.length()) { 76 | _offset = offset; 77 | throw new ArrayIndexOutOfBoundsException("Wait for more data."); 78 | } 79 | 80 | return new Reply(type, _buffer.getBuffer(start, end)); 81 | } else if (type == '*') { 82 | offset = _offset; 83 | packetSize = parsePacketSize(); 84 | 85 | if (packetSize < 0) { 86 | return null; 87 | } 88 | 89 | if (packetSize > bytesRemaining()) { 90 | _offset = offset - 1; 91 | throw new ArrayIndexOutOfBoundsException("Wait for more data."); 92 | } 93 | 94 | Reply reply = new Reply(type, packetSize); 95 | 96 | byte ntype; 97 | Reply res; 98 | 99 | for (int i = 0; i < packetSize; i++) { 100 | ntype = _buffer.getByte(_offset++); 101 | 102 | if (_offset > _buffer.length()) { 103 | throw new ArrayIndexOutOfBoundsException("Wait for more data."); 104 | } 105 | res = parseResult(ntype); 106 | reply.set(i, res); 107 | } 108 | 109 | return reply; 110 | } 111 | 112 | throw new RuntimeException("Unsupported message type"); 113 | } 114 | 115 | public void handle(Buffer buffer) { 116 | append(buffer); 117 | 118 | byte type; 119 | Reply ret; 120 | int offset; 121 | 122 | loop: while (true) { 123 | offset = _offset; 124 | try { 125 | // at least 4 bytes: :1\r\n 126 | if (bytesRemaining() < 4) { 127 | break; 128 | } 129 | 130 | type = _buffer.getByte(_offset++); 131 | 132 | switch (type) { 133 | case '*': 134 | // set a rewind point. if a failure occurs, 135 | // wait for the next handle()/append() and try again 136 | offset = _offset - 1; 137 | case '+': 138 | case '-': 139 | case ':': 140 | case '$': 141 | ret = parseResult(type); 142 | 143 | if (ret == null) { 144 | break loop; 145 | } 146 | 147 | client.handleReply(ret); 148 | break; 149 | } 150 | } catch (ArrayIndexOutOfBoundsException err) { 151 | // catch the error (not enough data), rewind, and wait 152 | // for the next packet to appear 153 | _offset = offset; 154 | break; 155 | } 156 | } 157 | } 158 | 159 | private void append(Buffer newBuffer) { 160 | if (newBuffer == null) { 161 | return; 162 | } 163 | 164 | // first run 165 | if (_buffer == null) { 166 | _buffer = newBuffer; 167 | 168 | return; 169 | } 170 | 171 | // out of data 172 | if (_offset >= _buffer.length()) { 173 | _buffer = newBuffer; 174 | _offset = 0; 175 | 176 | return; 177 | } 178 | 179 | // very large packet 180 | if (_offset > 0) { 181 | _buffer = _buffer.getBuffer(_offset, _buffer.length()); 182 | } 183 | _buffer.appendBuffer(newBuffer); 184 | 185 | _offset = 0; 186 | } 187 | 188 | private int parsePacketSize() throws ArrayIndexOutOfBoundsException { 189 | int end = packetEndOffset(); 190 | String value = _buffer.getString(_offset, end - 1, _encoding); 191 | 192 | _offset = end + 1; 193 | 194 | long size = Long.parseLong(value); 195 | 196 | if (size > Integer.MAX_VALUE) { 197 | throw new RuntimeException("Cannot allocate more than " + Integer.MAX_VALUE + " bytes"); 198 | } 199 | 200 | if (size < Integer.MIN_VALUE) { 201 | throw new RuntimeException("Cannot allocate less than " + Integer.MIN_VALUE + " bytes"); 202 | } 203 | return (int) size; 204 | } 205 | 206 | private int packetEndOffset() throws ArrayIndexOutOfBoundsException { 207 | int offset = _offset; 208 | 209 | while (_buffer.getByte(offset) != '\r' && _buffer.getByte(offset + 1) != '\n') { 210 | offset++; 211 | 212 | if (offset >= _buffer.length()) { 213 | throw new ArrayIndexOutOfBoundsException("didn't see LF after NL reading multi bulk count (" + offset + " => " + _buffer.length() + ", " + _offset + ")"); 214 | } 215 | } 216 | 217 | offset++; 218 | return offset; 219 | } 220 | 221 | private int bytesRemaining() { 222 | return (_buffer.length() - _offset) < 0 ? 0 : (_buffer.length() - _offset); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/Command.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import org.vertx.java.core.Handler; 4 | import org.vertx.java.core.buffer.Buffer; 5 | import org.vertx.java.core.json.JsonArray; 6 | import org.vertx.java.core.json.JsonObject; 7 | import org.vertx.java.core.net.NetSocket; 8 | import org.vertx.java.core.streams.WriteStream; 9 | 10 | import java.nio.charset.Charset; 11 | 12 | public class Command { 13 | 14 | private static final byte ARGS_PREFIX = '*'; 15 | private static final byte[] CRLF = "\r\n".getBytes(); 16 | private static final byte BYTES_PREFIX = '$'; 17 | 18 | private static final byte[] NEG_ONE = convert(-1); 19 | 20 | // Cache 256 number conversions. That should cover a huge 21 | // percentage of numbers passed over the wire. 22 | private static final int NUM_MAP_LENGTH = 256; 23 | private static final byte[][] numMap = new byte[NUM_MAP_LENGTH][]; 24 | 25 | static { 26 | for (int i = 0; i < NUM_MAP_LENGTH; i++) { 27 | numMap[i] = convert(i); 28 | } 29 | } 30 | 31 | // Optimized for the direct to ASCII bytes case 32 | // About 5x faster than using Long.toString.getBytes 33 | private static byte[] numToBytes(long value) { 34 | if (value >= 0 && value < NUM_MAP_LENGTH) { 35 | int index = (int) value; 36 | return numMap[index]; 37 | } else if (value == -1) { 38 | return NEG_ONE; 39 | } 40 | return convert(value); 41 | } 42 | 43 | private static byte[] convert(long value) { 44 | boolean negative = value < 0; 45 | // Checked javadoc: If the argument is equal to 10^n for integer n, then the result is n. 46 | // Also, if negative, leave another slot for the sign. 47 | long abs = Math.abs(value); 48 | int index = (value == 0 ? 0 : (int) Math.log10(abs)) + (negative ? 2 : 1); 49 | byte[] bytes = new byte[index]; 50 | // Put the sign in the slot we saved 51 | if (negative) bytes[0] = '-'; 52 | long next = abs; 53 | while ((next /= 10) > 0) { 54 | bytes[--index] = (byte) ('0' + (abs % 10)); 55 | abs = next; 56 | } 57 | bytes[--index] = (byte) ('0' + abs); 58 | return bytes; 59 | } 60 | 61 | private void appendToBuffer(final Object value, final Charset encoding, final Buffer buffer) { 62 | buffer.appendByte(BYTES_PREFIX); 63 | if (value == null) { 64 | buffer.appendByte((byte) '0'); 65 | buffer.appendBytes(CRLF); 66 | buffer.appendBytes(CRLF); 67 | } else { 68 | byte[] bytes; 69 | // Possible types are: String, JsonObject, JsonArray, JsonElement, Number, Boolean, byte[] 70 | 71 | if (value instanceof byte[]) { 72 | bytes = (byte[]) value; 73 | } else if (value instanceof Buffer) { 74 | bytes = ((Buffer) value).getBytes(); 75 | } else if (value instanceof String) { 76 | bytes = ((String) value).getBytes(encoding); 77 | } else if (value instanceof Byte) { 78 | bytes = numToBytes((Byte) value); 79 | } else if (value instanceof Short) { 80 | bytes = numToBytes((Short) value); 81 | } else if (value instanceof Integer) { 82 | bytes = numToBytes((Integer) value); 83 | } else if (value instanceof Long) { 84 | bytes = numToBytes((Long) value); 85 | } else { 86 | bytes = value.toString().getBytes(encoding); 87 | } 88 | 89 | buffer.appendBytes(numToBytes(bytes.length)); 90 | 91 | buffer.appendBytes(CRLF); 92 | buffer.appendBytes(bytes); 93 | buffer.appendBytes(CRLF); 94 | } 95 | } 96 | 97 | private final Buffer buffer; 98 | private int expectedReplies = 1; 99 | private Handler handler; 100 | 101 | public Command(JsonObject json, Charset encoding) { 102 | 103 | String command = json.getString("command"); 104 | JsonArray args = json.getArray("args"); 105 | 106 | int totalArgs; 107 | if (args == null) { 108 | totalArgs = 0; 109 | } else { 110 | totalArgs = args.size(); 111 | } 112 | 113 | int spc = command.indexOf(' '); // there are commands which are multi word 114 | String extraCommand = null; 115 | 116 | if (spc != -1) { 117 | extraCommand = command.substring(spc + 1); 118 | command = command.substring(0, spc); 119 | } 120 | 121 | // serialize the request 122 | buffer = new Buffer(); 123 | buffer.appendByte(ARGS_PREFIX); 124 | if (extraCommand == null) { 125 | buffer.appendBytes(numToBytes(totalArgs + 1)); 126 | } else { 127 | buffer.appendBytes(numToBytes(totalArgs + 2)); 128 | } 129 | buffer.appendBytes(CRLF); 130 | // serialize the command 131 | appendToBuffer(command.getBytes(encoding), encoding, buffer); 132 | if (extraCommand != null) { 133 | appendToBuffer(extraCommand.getBytes(encoding), encoding, buffer); 134 | } 135 | 136 | // serialize arguments 137 | for (int i = 0; i < totalArgs; i++) { 138 | appendToBuffer(args.get(i), encoding, buffer); 139 | } 140 | } 141 | 142 | public Command(String command, Object... args) { 143 | 144 | this.expectedReplies = 1; 145 | this.handler = null; 146 | 147 | int totalArgs; 148 | if (args == null) { 149 | totalArgs = 0; 150 | } else { 151 | totalArgs = args.length; 152 | } 153 | 154 | int spc = command.indexOf(' '); // there are commands which are multi word 155 | String extraCommand = null; 156 | 157 | if (spc != -1) { 158 | extraCommand = command.substring(spc + 1); 159 | command = command.substring(0, spc); 160 | } 161 | 162 | // serialize the request 163 | buffer = new Buffer(); 164 | buffer.appendByte(ARGS_PREFIX); 165 | if (extraCommand == null) { 166 | buffer.appendBytes(numToBytes(totalArgs + 1)); 167 | } else { 168 | buffer.appendBytes(numToBytes(totalArgs + 2)); 169 | } 170 | buffer.appendBytes(CRLF); 171 | // serialize the command 172 | Charset defaultCharset = Charset.defaultCharset(); 173 | appendToBuffer(command.getBytes(defaultCharset), defaultCharset, buffer); 174 | if (extraCommand != null) { 175 | appendToBuffer(extraCommand.getBytes(defaultCharset), defaultCharset, buffer); 176 | } 177 | 178 | // serialize arguments 179 | for (int i = 0; i < totalArgs; i++) { 180 | appendToBuffer(args[i], defaultCharset, buffer); 181 | } 182 | } 183 | 184 | public Command setExpectedReplies(int expectedReplies) { 185 | this.expectedReplies = expectedReplies; 186 | return this; 187 | } 188 | 189 | public Command setHandler(Handler handler) { 190 | this.handler = handler; 191 | return this; 192 | } 193 | 194 | public void writeTo(WriteStream writeStream) { 195 | writeStream.write(buffer); 196 | } 197 | 198 | public int getExpectedReplies() { 199 | return expectedReplies; 200 | } 201 | 202 | public Handler getHandler() { 203 | return handler; 204 | } 205 | 206 | } 207 | -------------------------------------------------------------------------------- /mod-client/src/main/java/io/vertx/java/redis/AbstractRedisClient.java: -------------------------------------------------------------------------------- 1 | package io.vertx.java.redis; 2 | 3 | import org.vertx.java.core.AsyncResult; 4 | import org.vertx.java.core.AsyncResultHandler; 5 | import org.vertx.java.core.Handler; 6 | import org.vertx.java.core.eventbus.EventBus; 7 | import org.vertx.java.core.eventbus.Message; 8 | import org.vertx.java.core.json.JsonArray; 9 | import org.vertx.java.core.json.JsonElement; 10 | import org.vertx.java.core.json.JsonObject; 11 | import org.vertx.java.platform.Container; 12 | 13 | abstract class AbstractRedisClient { 14 | 15 | final EventBus eventBus; 16 | final String redisAddress; 17 | 18 | AbstractRedisClient(EventBus eventBus, String redisAddress) { 19 | this.eventBus = eventBus; 20 | this.redisAddress = redisAddress; 21 | } 22 | 23 | public final void deployModule(Container container) { 24 | deployModule(container, "localhost", 6379, "UTF-8", false, null, 0, 1, null); 25 | } 26 | 27 | public final void deployModule(Container container, AsyncResultHandler handler) { 28 | deployModule(container, "localhost", 6379, "UTF-8", false, null, 0, 1, handler); 29 | } 30 | 31 | public final void deployModule(Container container, String hostname, int port) { 32 | deployModule(container, hostname, port, "UTF-8", false, null, 0, 1, null); 33 | } 34 | 35 | public final void deployModule(Container container, String hostname, int port, AsyncResultHandler handler) { 36 | deployModule(container, hostname, port, "UTF-8", false, null, 0, 1, handler); 37 | } 38 | 39 | public final void deployModule(Container container, String hostname, int port, int instances) { 40 | deployModule(container, hostname, port, "UTF-8", false, null, 0, instances, null); 41 | } 42 | 43 | public final void deployModule(Container container, String hostname, int port, int instances, AsyncResultHandler handler) { 44 | deployModule(container, hostname, port, "UTF-8", false, null, 0, instances, handler); 45 | } 46 | 47 | private static AsyncResult createAsyncResult(final boolean succeed, final String result, final Throwable cause) { 48 | return new AsyncResult() { 49 | @Override 50 | public String result() { 51 | return result; 52 | } 53 | 54 | @Override 55 | public Throwable cause() { 56 | return cause; 57 | } 58 | 59 | @Override 60 | public boolean succeeded() { 61 | return succeed; 62 | } 63 | 64 | @Override 65 | public boolean failed() { 66 | return !succeed; 67 | } 68 | }; 69 | } 70 | 71 | public final void deployModule(Container container, JsonObject config, final AsyncResultHandler handler) { 72 | String mod = "io.vertx~mod-redis~1.1.5"; 73 | int instances = config.getInteger("instances", 1); 74 | 75 | if (handler != null) { 76 | container.deployModule(mod, config, instances, handler); 77 | } else { 78 | container.deployModule(mod, config, instances); 79 | } 80 | } 81 | 82 | public final void deployModule(Container container, String hostname, int port, String encoding, boolean binary, final String auth, final int select, int instances, final AsyncResultHandler handler) { 83 | JsonObject config = new JsonObject() 84 | .putString("host", hostname) 85 | .putNumber("port", port) 86 | .putString("address", redisAddress) 87 | .putString("encoding", encoding) 88 | .putBoolean("binary", binary) 89 | .putString("auth", auth) 90 | .putNumber("select", select) 91 | .putNumber("instances", instances); 92 | 93 | deployModule(container, config, handler); 94 | } 95 | 96 | private static void serializeArg(JsonArray redisArgs, Object arg) { 97 | if (arg == null) { 98 | redisArgs.add(null); 99 | } else { 100 | if (arg instanceof String) { 101 | redisArgs.addString((String) arg); 102 | } else if (arg instanceof Object[]) { 103 | for (Object o : (Object[]) arg) { 104 | redisArgs.add(o); 105 | } 106 | } else if (arg instanceof JsonObject) { 107 | redisArgs.addObject((JsonObject) arg); 108 | } else if (arg instanceof JsonArray) { 109 | redisArgs.addArray((JsonArray) arg); 110 | } else if (arg instanceof JsonElement) { 111 | redisArgs.addElement((JsonElement) arg); 112 | } else if (arg instanceof Number) { 113 | redisArgs.addNumber((Number) arg); 114 | } else if (arg instanceof Boolean) { 115 | redisArgs.addBoolean((Boolean) arg); 116 | } else if (arg instanceof byte[]) { 117 | redisArgs.addBinary((byte[]) arg); 118 | } else { 119 | throw new RuntimeException("Unsupported type: " + arg.getClass().getName()); 120 | } 121 | } 122 | } 123 | 124 | @SuppressWarnings("unchecked") 125 | final void send(RedisCommand command, Object... args) { 126 | 127 | JsonObject json = new JsonObject(); 128 | JsonArray redisArgs = new JsonArray(); 129 | 130 | int totalArgs = 0; 131 | boolean expectResult = false; 132 | Handler> messageHandler = null; 133 | 134 | // verify if there are args 135 | if (args != null && args.length > 0) { 136 | // verify if the last one is a Handler 137 | Object last = args[args.length - 1]; 138 | totalArgs = args.length; 139 | if (last instanceof Handler) { 140 | // the caller expects a result 141 | expectResult = true; 142 | totalArgs--; 143 | messageHandler = (Handler>) last; 144 | } 145 | } 146 | 147 | // serialize the request 148 | json.putString("command", command.getCommand()); 149 | 150 | // handle special hash commands 151 | switch (command) 152 | { 153 | case MSET: 154 | case MSETNX: 155 | case HMSET: 156 | case ZADD: 157 | if (totalArgs == 2 && args[1] instanceof JsonObject) { 158 | // there are only 2 arguments and the last is a json object, convert the hash into a redis command 159 | serializeArg(redisArgs, args[0]); 160 | JsonObject hash = (JsonObject) args[1]; 161 | for (String key : hash.getFieldNames()) { 162 | serializeArg(redisArgs, key); 163 | serializeArg(redisArgs, hash.getField(key)); 164 | } 165 | 166 | // remove these 2 since they are already added to the args array 167 | totalArgs = 0; 168 | } 169 | break; 170 | } 171 | 172 | // serialize arguments 173 | for (int i = 0; i < totalArgs; i++) { 174 | serializeArg(redisArgs, args[i]); 175 | } 176 | 177 | json.putArray("args", redisArgs); 178 | 179 | if (expectResult) { 180 | eventBus.send(redisAddress, json, messageHandler); 181 | } else { 182 | eventBus.send(redisAddress, json); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /mod/src/test/groovy/io/vertx/redis/GRedisPubSubTester.groovy: -------------------------------------------------------------------------------- 1 | package io.vertx.redis 2 | 3 | import org.junit.Test 4 | import org.vertx.java.core.AsyncResult 5 | import org.vertx.java.core.AsyncResultHandler 6 | import org.vertx.java.core.Handler 7 | import org.vertx.java.core.eventbus.EventBus 8 | import org.vertx.java.core.eventbus.Message 9 | import org.vertx.java.core.json.JsonObject 10 | import org.vertx.testtools.TestVerticle 11 | import static org.vertx.testtools.VertxAssert.* 12 | 13 | class GRedisPubSubTester extends TestVerticle { 14 | 15 | private final String pubAddress = "test.redis.pub" 16 | private final String subAddress = "test.redis.sub" 17 | private EventBus eb 18 | 19 | private void appReady() { 20 | super.start() 21 | } 22 | 23 | void start() { 24 | initialize(vertx) 25 | eb = vertx.eventBus() 26 | JsonObject pubConfig = new JsonObject() 27 | pubConfig.putString("address", pubAddress) 28 | JsonObject subConfig = new JsonObject() 29 | subConfig.putString("address", subAddress) 30 | 31 | // deploy 1 module for publishing 32 | container.deployModule(System.getProperty("vertx.modulename"), pubConfig, 1, new AsyncResultHandler() { 33 | @Override 34 | void handle(AsyncResult event1) { 35 | // deploy 1 module for subscribing 36 | container.deployModule(System.getProperty("vertx.modulename"), subConfig, 1, new AsyncResultHandler() { 37 | @Override 38 | void handle(AsyncResult event2) { 39 | appReady() 40 | } 41 | }) 42 | } 43 | }) 44 | } 45 | 46 | /** 47 | * Helper method to allow simple Groovy closure calls and simplified maps as json messages 48 | * @param json message 49 | * @param closure response handler 50 | */ 51 | void redis(String address, Map json, boolean fail = false, Closure closure) { 52 | eb.send(address, new JsonObject(json), new Handler>() { 53 | public void handle(Message reply) { 54 | if (fail) { 55 | assertEquals("error", reply.body.getString("status")) 56 | } else { 57 | assertEquals("ok", reply.body.getString("status")) 58 | } 59 | 60 | closure.call(reply) 61 | } 62 | }) 63 | } 64 | 65 | static String makeKey() { 66 | return UUID.randomUUID().toString() 67 | } 68 | 69 | void assertNumber(expected, value) { 70 | assertEquals(expected, value.body.getNumber("value")) 71 | } 72 | 73 | void assertArray(expected, value) { 74 | def array = value.body.getArray("value") 75 | assertNotNull(array) 76 | assertEquals(expected.size(), array.size()) 77 | 78 | for (int i = 0; i < array.size(); i++) { 79 | if (expected[i] == null) { 80 | assertNull(array.get(i)) 81 | } else { 82 | assertEquals(expected[i], array.get(i)) 83 | } 84 | } 85 | } 86 | 87 | @Test 88 | void testPubSub() { 89 | def message = makeKey() 90 | 91 | // register a handler for the incoming message 92 | eb.registerHandler("${subAddress}.ch1", new Handler>() { 93 | @Override 94 | void handle(Message received) { 95 | def value = received.body.getField('value') 96 | assertEquals('ch1', value.getField('channel')) 97 | assertEquals(message, value.getField('message')) 98 | testComplete() 99 | } 100 | }); 101 | 102 | // on sub address subscribe to channel ch1 103 | redis(subAddress, [command: 'subscribe', args: ['ch1']]) { subscribe -> 104 | assertArray(['subscribe', 'ch1', 1], subscribe) 105 | 106 | // on pub address publish a message 107 | redis(pubAddress, [command: 'publish', args: ['ch1', message]]) { publish -> 108 | assertNumber(1, publish) 109 | } 110 | } 111 | } 112 | 113 | @Test 114 | void testPubSubPattern() { 115 | 116 | def worldNews = 'hello world' 117 | def technologyNews = 'hello vertx' 118 | def inbox = [] 119 | 120 | // register a handler for all incoming messages 121 | eb.registerHandler("${subAddress}.news.*", new Handler>() { 122 | @Override 123 | void handle(Message received) { 124 | inbox.add(received.body.getField('value')) 125 | 126 | if (inbox.size() == 2) { 127 | if ((worldNews.equals(inbox[0].getField('message')) && technologyNews.equals(inbox[1].getField('message'))) || (worldNews.equals(inbox[1].getField('message')) && technologyNews.equals(inbox[0].getField('message')))) { 128 | testComplete() 129 | } 130 | } 131 | } 132 | }); 133 | 134 | // on sub address subscribe to channels news.* 135 | redis(subAddress, [command: 'psubscribe', args: ['news.*']]) { subscribe -> 136 | assertArray(['psubscribe', 'news.*', 1], subscribe) 137 | 138 | // on pub address publish a message to news.wold 139 | redis(pubAddress, [command: 'publish', args: ['news.world', worldNews]]) { publish -> 140 | assertNumber(1, publish) 141 | } 142 | // on pub address publish a message to news.technology 143 | redis(pubAddress, [command: 'publish', args: ['news.technology', technologyNews]]) { publish -> 144 | assertNumber(1, publish) 145 | } 146 | } 147 | } 148 | 149 | private void lateJoinHelper(String message) { 150 | JsonObject subConfig2 = new JsonObject() 151 | subConfig2.putString("address", "test.redis.sub2") 152 | 153 | container.deployModule(System.getProperty("vertx.modulename"), subConfig2, 1, new AsyncResultHandler() { 154 | public void handle(final AsyncResult subDeploymentId) { 155 | // on sub address subscribe to channel ch2 156 | redis("test.redis.sub2", [command: 'subscribe', args: ['ch2']]) { subscribe -> 157 | assertArray(['subscribe', 'ch2', 1], subscribe) 158 | 159 | // on pub address publish a message 160 | redis(pubAddress, [command: 'publish', args: ['ch2', message]]) { publish -> 161 | assertNumber(2, publish) 162 | } 163 | } 164 | } 165 | }) 166 | } 167 | 168 | @Test 169 | void testLateJoin() { 170 | def message = makeKey() 171 | 172 | // register a handler for the incoming message 173 | eb.registerHandler("${subAddress}.ch2", new Handler>() { 174 | @Override 175 | void handle(Message received) { 176 | def value = received.body.getField('value') 177 | assertEquals('ch2', value.getField('channel')) 178 | assertEquals(message, value.getField('message')) 179 | testComplete() 180 | } 181 | }); 182 | 183 | // on sub address subscribe to channel ch2 184 | redis(subAddress, [command: 'subscribe', args: ['ch2']]) { subscribe -> 185 | assertArray(['subscribe', 'ch2', 1], subscribe) 186 | 187 | // deploy a new sub 188 | lateJoinHelper(message) 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /gradle/vertx.gradle: -------------------------------------------------------------------------------- 1 | import org.vertx.java.platform.impl.cli.Starter 2 | 3 | /* 4 | * Copyright 2012 the original author or authors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | apply plugin: 'java' 20 | apply plugin: 'groovy' 21 | apply plugin: 'idea' 22 | apply plugin: 'eclipse' 23 | 24 | def cpSeparator = System.getProperty("path.separator") 25 | 26 | // We have to explicitly load props from the user home dir - on CI we set 27 | // GRADLE_USER_HOME to a different dir to avoid problems with concurrent builds corrupting 28 | // a shared Maven local and using Gradle wrapper concurrently 29 | loadProperties("${System.getProperty('user.home')}/.gradle/gradle.properties") 30 | 31 | apply from: "$rootDir/gradle/maven.gradle" 32 | 33 | group = modowner 34 | archivesBaseName = modname 35 | 36 | defaultTasks = ['assemble'] 37 | 38 | sourceCompatibility = '1.7' 39 | targetCompatibility = '1.7' 40 | 41 | project.ext.moduleName = "$modowner~$modname~$version" 42 | 43 | configurations { 44 | provided 45 | testCompile.extendsFrom provided 46 | } 47 | 48 | repositories { 49 | if (System.getenv("VERTX_DISABLE_MAVENLOCAL") == null) { 50 | // We don't want to use mavenLocal when running on CI - mavenLocal is only useful in Gradle for 51 | // publishing artifacts locally for development purposes - maven local is also not threadsafe when there 52 | // are concurrent builds 53 | mavenLocal() 54 | } 55 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } 56 | mavenCentral() 57 | } 58 | 59 | dependencies { 60 | provided "io.vertx:vertx-core:$vertxVersion" 61 | provided "io.vertx:vertx-platform:$vertxVersion" 62 | testCompile "junit:junit:$junitVersion" 63 | testCompile "io.vertx:testtools:$toolsVersion" 64 | } 65 | 66 | // This sets up the classpath for the script itself 67 | buildscript { 68 | 69 | repositories { 70 | if (System.getenv("VERTX_DISABLE_MAVENLOCAL") == null) { 71 | // We don't want to use mavenLocal when running on CI - mavenLocal is only useful in Gradle for 72 | // publishing artifacts locally for development purposes - maven local is also not threadsafe when there 73 | // are concurrent builds 74 | mavenLocal() 75 | } 76 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } 77 | mavenCentral() 78 | } 79 | 80 | dependencies { 81 | classpath "io.vertx:vertx-core:$vertxVersion" 82 | classpath "io.vertx:vertx-platform:$vertxVersion" 83 | classpath "io.vertx:vertx-hazelcast:$vertxVersion" 84 | classpath files(["$projectDir/src/main/resources"]) 85 | } 86 | } 87 | 88 | sourceSets { 89 | main { 90 | compileClasspath = compileClasspath + configurations.provided 91 | } 92 | } 93 | 94 | task copyMod( type:Copy, dependsOn: 'classes', description: 'Assemble the module into the local mods directory' ) { 95 | into "$projectDir/build/mods/$moduleName" 96 | from compileJava 97 | from "$projectDir/src/main/resources" 98 | into( "$projectDir/lib" ) { 99 | from configurations.compile 100 | } 101 | } 102 | 103 | task modZip( type: Zip, dependsOn: 'pullInDeps', description: 'Package the module .zip file') { 104 | group = 'vert.x' 105 | classifier = "mod" 106 | description = "Assembles a vert.x module" 107 | destinationDir = project.file("$projectDir/build/libs") 108 | archiveName = "${modname}-${version}" + ".zip" 109 | from copyMod 110 | } 111 | 112 | task sourceJar(type: Jar) { 113 | description = 'Builds a source jar artifact suitable for maven deployment.' 114 | classifier = 'sources' 115 | from sourceSets.main.java 116 | } 117 | 118 | javadoc.classpath += configurations.provided 119 | 120 | task javadocJar(type: Jar) { 121 | description = 'Builds a javadoc jar artifact suitable for maven deployment.' 122 | classifier = 'javadoc' 123 | from javadoc.destinationDir 124 | } 125 | javadocJar.dependsOn javadoc 126 | 127 | build.dependsOn sourceJar, javadocJar 128 | 129 | artifacts { 130 | archives sourceJar, javadocJar, modZip 131 | } 132 | 133 | 134 | test { 135 | dependsOn copyMod 136 | 137 | // Make sure tests are always run! 138 | outputs.upToDateWhen { false } 139 | 140 | // Show output 141 | testLogging.showStandardStreams = true 142 | 143 | testLogging { exceptionFormat "full" } 144 | 145 | systemProperty 'vertx.mods', "$projectDir/build/mods" 146 | } 147 | 148 | task runModIDEA(dependsOn: copyMod, description: 'Run the module from the resources in IntelliJ') << { 149 | runModWithClasspath("$projectDir/src/main/resources/${cpSeparator}$projectDir/src/test/resources/${cpSeparator}" + 150 | "$projectDir/out/production/${project.name}/${cpSeparator}$projectDir/out/test/${project.name}/"); 151 | } 152 | 153 | task runModEclipse(dependsOn: copyMod, description: 'Run the module from the resources in Eclipse') << { 154 | runModWithClasspath("$projectDir/src/main/resources/${cpSeparator}$projectDir/src/test/resources/${cpSeparator}$projectDir/bin/"); 155 | } 156 | 157 | def runModWithClasspath(String classpath) { 158 | setSysProps() 159 | def args = ['runmod', moduleName] 160 | def args2 = runModArgs.split("\\s+") 161 | // Ignore any -cp 162 | boolean ignoring = false 163 | for (String arg: args2) { 164 | if (arg == '-cp') { 165 | ignoring = true 166 | } else if (!ignoring) { 167 | args.add(arg) 168 | } else { 169 | ignoring = false 170 | } 171 | } 172 | args.add('-cp') 173 | args.add(classpath) 174 | Starter.main(args as String[]) 175 | } 176 | 177 | task runMod(dependsOn: copyMod, description: 'Run the module using all the build dependencies (not using installed vertx') << { 178 | setSysProps() 179 | def args = ['runmod', moduleName] 180 | def args2 = runModArgs.split("\\s+") 181 | args.addAll(args2) 182 | Starter.main(args as String[]) 183 | } 184 | 185 | task pullInDeps(dependsOn: copyMod, description: 'Pull in all the module dependencies for the module into the nested mods directory') << { 186 | if (pullInDeps == 'true') { 187 | setSysProps() 188 | def args = ['pulldeps', moduleName] 189 | Starter.main(args as String[]) 190 | } 191 | } 192 | 193 | task fatJar(dependsOn: modZip, description: 'Creates a fat executable jar which contains everything needed to run the module') << { 194 | if (createFatJar == 'true') { 195 | setSysProps() 196 | def args = ['fatjar', moduleName, '-d', "$projectDir/build/libs"] 197 | Starter.main(args as String[]) 198 | } 199 | } 200 | 201 | def setSysProps() { 202 | System.setProperty("vertx.clusterManagerFactory", "org.vertx.java.spi.cluster.impl.hazelcast.HazelcastClusterManagerFactory") 203 | System.setProperty("vertx.mods", "$projectDir/build/mods") 204 | } 205 | 206 | def loadProperties(String sourceFileName) { 207 | def config = new Properties() 208 | def propFile = new File(sourceFileName) 209 | if (propFile.canRead()) { 210 | config.load(new FileInputStream(propFile)) 211 | for (Map.Entry property in config) { 212 | project.ext[property.key] = property.value; 213 | } 214 | } 215 | } 216 | 217 | // Map the 'provided' dependency configuration to the appropriate IDEA visibility scopes. 218 | plugins.withType(IdeaPlugin) { 219 | idea { 220 | module { 221 | scopes.PROVIDED.plus += configurations.provided 222 | scopes.COMPILE.minus += configurations.provided 223 | scopes.TEST.minus += configurations.provided 224 | scopes.RUNTIME.minus += configurations.provided 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/RedisMod.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import io.vertx.redis.impl.RedisSubscriptions; 4 | import org.vertx.java.busmods.BusModBase; 5 | import org.vertx.java.core.Handler; 6 | import org.vertx.java.core.eventbus.Message; 7 | import org.vertx.java.core.json.JsonArray; 8 | import org.vertx.java.core.json.JsonObject; 9 | import io.vertx.redis.impl.MessageHandler; 10 | 11 | import java.nio.charset.Charset; 12 | 13 | @SuppressWarnings("unused") 14 | public class RedisMod extends BusModBase implements Handler> { 15 | 16 | private RedisConnection redisClient; 17 | private RedisSubscriptions subscriptions = new RedisSubscriptions(); 18 | 19 | private String encoding; 20 | private Charset charset; 21 | private String baseAddress; 22 | 23 | private enum ResponseTransform { 24 | NONE, 25 | ARRAY_TO_OBJECT, 26 | INFO 27 | } 28 | 29 | @Override 30 | public void start() { 31 | super.start(); 32 | 33 | final String host = getOptionalStringConfig("host", "localhost"); 34 | final int port = getOptionalIntConfig("port", 6379); 35 | final String encoding = getOptionalStringConfig("encoding", null); 36 | final boolean binary = getOptionalBooleanConfig("binary", false); 37 | // extra options that are nice to have 38 | final String auth = getOptionalStringConfig("auth", null); 39 | final int select = getOptionalIntConfig("select", 0); 40 | 41 | if (binary) { 42 | logger.warn("Binary mode is not implemented yet!!!"); 43 | } 44 | 45 | if (encoding != null) { 46 | this.encoding = encoding; 47 | } else { 48 | this.encoding = "UTF-8"; 49 | } 50 | 51 | charset = Charset.forName(this.encoding); 52 | 53 | redisClient = new RedisConnection(vertx, logger, host, port, auth, select, subscriptions); 54 | redisClient.connect(null); 55 | 56 | baseAddress = getOptionalStringConfig("address", "io.vertx.mod-redis"); 57 | eb.registerHandler(baseAddress, this); 58 | } 59 | 60 | private ResponseTransform getResponseTransformFor(String command) { 61 | if (command.equals("hgetall")) { 62 | return ResponseTransform.ARRAY_TO_OBJECT; 63 | } 64 | if (command.equals("info")) { 65 | return ResponseTransform.INFO; 66 | } 67 | 68 | return ResponseTransform.NONE; 69 | } 70 | 71 | @Override 72 | public void handle(final Message message) { 73 | 74 | String command = message.body().getString("command"); 75 | final Object o = message.body().getField("args"); 76 | final JsonArray args; 77 | 78 | if (o != null) { 79 | if (o instanceof JsonArray) { 80 | args = (JsonArray) o; 81 | } else { 82 | args = new JsonArray().add(o); 83 | } 84 | } else { 85 | args = null; 86 | } 87 | 88 | if (command == null) { 89 | sendError(message, "command must be specified"); 90 | return; 91 | } else { 92 | command = command.toLowerCase(); 93 | } 94 | 95 | final ResponseTransform transform = getResponseTransformFor(command); 96 | 97 | // subscribe/psubscribe and unsubscribe/punsubscribe commands can have multiple (including zero) replies 98 | int expectedReplies = 1; 99 | 100 | switch (command) { 101 | // argument "pattern" ["pattern"...] 102 | case "psubscribe": 103 | // in this case we need also to register handlers 104 | if (args == null) { 105 | sendError(message, "at least one pattern is required!"); 106 | return; 107 | } 108 | expectedReplies = args.size(); 109 | for (Object obj : args) { 110 | String pattern = (String) obj; 111 | // compose the listening address as base + . + pattern 112 | final String vertxChannel = baseAddress + "." + pattern; 113 | subscriptions.registerPatternSubscribeHandler(pattern, new MessageHandler() { 114 | @Override 115 | public void handle(String pattern, Reply[] replyData) { 116 | JsonObject replyMessage = new JsonObject(); 117 | replyMessage.putString("status", "ok"); 118 | JsonObject message = new JsonObject(); 119 | message.putString("pattern", pattern); 120 | message.putString("channel", replyData[2].toString(encoding)); 121 | message.putString("message", replyData[3].toString(encoding)); 122 | replyMessage.putObject("value", message); 123 | eb.send(vertxChannel, replyMessage); 124 | } 125 | }); 126 | } 127 | break; 128 | // argument "channel" ["channel"...] 129 | case "subscribe": 130 | if (args == null) { 131 | sendError(message, "at least one pattern is required!"); 132 | return; 133 | } 134 | // in this case we need also to register handlers 135 | expectedReplies = args.size(); 136 | for (Object obj : args) { 137 | String channel = (String) obj; 138 | // compose the listening address as base + . + channel 139 | final String vertxChannel = baseAddress + "." + channel; 140 | subscriptions.registerChannelSubscribeHandler(channel, new MessageHandler() { 141 | @Override 142 | public void handle(String channel, Reply[] replyData) { 143 | JsonObject replyMessage = new JsonObject(); 144 | replyMessage.putString("status", "ok"); 145 | JsonObject message = new JsonObject(); 146 | message.putString("channel", channel); 147 | message.putString("message", replyData[2].toString(encoding)); 148 | replyMessage.putObject("value", message); 149 | eb.send(vertxChannel, replyMessage); 150 | } 151 | }); 152 | } 153 | break; 154 | // argument ["pattern" ["pattern"...]] 155 | case "punsubscribe": 156 | // unregister all channels 157 | if (args == null || args.size() == 0) { 158 | // unsubscribe all 159 | expectedReplies = subscriptions.patternSize(); 160 | subscriptions.unregisterPatternSubscribeHandler(null); 161 | } else { 162 | expectedReplies = args.size(); 163 | for (Object obj : args) { 164 | String pattern = (String) obj; 165 | subscriptions.unregisterPatternSubscribeHandler(pattern); 166 | } 167 | } 168 | break; 169 | // argument ["channel" ["channel"...]] 170 | case "unsubscribe": 171 | // unregister all channels 172 | if (args == null || args.size() == 0) { 173 | // unsubscribe all 174 | expectedReplies = subscriptions.channelSize(); 175 | subscriptions.unregisterChannelSubscribeHandler(null); 176 | } else { 177 | expectedReplies = args.size(); 178 | for (Object obj : args) { 179 | String channel = (String) obj; 180 | subscriptions.unregisterChannelSubscribeHandler(channel); 181 | } 182 | } 183 | break; 184 | } 185 | 186 | redisClient.send(new Command(message.body(), charset).setExpectedReplies(expectedReplies).setHandler(new Handler() { 187 | @Override 188 | public void handle(Reply reply) { 189 | processReply(message, reply, transform); 190 | } 191 | })); 192 | } 193 | 194 | private void processReply(Message message, Reply reply, ResponseTransform transform) { 195 | JsonObject replyMessage; 196 | switch (reply.type()) { 197 | case '-': // Error 198 | sendError(message, reply.toString()); 199 | return; 200 | case '+': // Status 201 | replyMessage = new JsonObject(); 202 | replyMessage.putString("value", reply.toString()); 203 | sendOK(message, replyMessage); 204 | return; 205 | case '$': // Bulk 206 | replyMessage = new JsonObject(); 207 | if (transform == ResponseTransform.INFO) { 208 | String info = reply.toString(encoding); 209 | String lines[] = info.split("\\r?\\n"); 210 | JsonObject value = new JsonObject(); 211 | JsonObject section = null; 212 | for (String line : lines) { 213 | if (line.length() == 0) { 214 | // end of section 215 | section = null; 216 | continue; 217 | } 218 | 219 | if (line.charAt(0) == '#') { 220 | // begin section 221 | section = new JsonObject(); 222 | // create a sub key with the section name 223 | value.putObject(line.substring(2).toLowerCase(), section); 224 | } else { 225 | // entry in section 226 | int split = line.indexOf(':'); 227 | if (section == null) { 228 | value.putString(line.substring(0, split), line.substring(split + 1)); 229 | } else { 230 | section.putString(line.substring(0, split), line.substring(split + 1)); 231 | } 232 | } 233 | } 234 | replyMessage.putObject("value", value); 235 | } else { 236 | replyMessage.putString("value", reply.toString(encoding)); 237 | } 238 | sendOK(message, replyMessage); 239 | return; 240 | case '*': // Multi 241 | replyMessage = new JsonObject(); 242 | if (transform == ResponseTransform.ARRAY_TO_OBJECT) { 243 | replyMessage.putObject("value", reply.toJsonObject(encoding)); 244 | } else { 245 | replyMessage.putArray("value", reply.toJsonArray(encoding)); 246 | } 247 | sendOK(message, replyMessage); 248 | return; 249 | case ':': // Integer 250 | replyMessage = new JsonObject(); 251 | replyMessage.putNumber("value", reply.toNumber()); 252 | sendOK(message, replyMessage); 253 | return; 254 | default: 255 | sendError(message, "Unknown message type"); 256 | } 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vert.x 2.x is **deprecated** - use instead http://vertx.io/docs/vertx-redis-client/java/ 2 | 3 | ## Redis busmod for Vert.x 4 | 5 | This module allows data to be saved, retrieved, searched for, and deleted in a Redis. Redis is an open source, BSD 6 | licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, 7 | hashes, lists, sets and sorted sets. To use this module you must have a Redis server instance running on your network. 8 | 9 | ### Dependencies 10 | 11 | This module requires a Redis server to be available on the network. 12 | 13 | ### Which module should I use? 14 | 15 | This project provides 2 modules: 16 | 17 | * `io.vertx~mod-redis~1.1.5` - The runnable module that allows direct access to Redis 18 | * `io.vertx~mod-redis-client~1.1.5` - The NON runnable that creates a simple API on top of the previous 19 | 20 | ### mod-redis 21 | 22 | The module name is `io.vertx~mod-redis~1.1.5`. 23 | 24 | #### Configuration 25 | 26 | The module takes the following configuration: 27 | 28 | { 29 | "address":
, 30 | "host": , 31 | "port": , 32 | "encoding": , 33 | "binary": , 34 | "auth": , 35 | "select": 36 | } 37 | 38 | For example: 39 | 40 | { 41 | "address": "test.my_redis", 42 | "host": "localhost", 43 | "port": 6379 44 | } 45 | 46 | Let's take a look at each field in turn: 47 | 48 | * `address` The main address for the module. Every module has a main address. Defaults to `io.vertx.mod-redis`. 49 | * `host` Host name or ip address of the Redis instance. Defaults to `localhost`. 50 | * `port` Port at which the Redis instance is listening. Defaults to `6379`. 51 | * `encoding` The character encoding for string conversions (e.g.: `UTF-8`, `ISO-8859-1`, `US-ASCII`). Defaults to the platform default. 52 | * `binary` To be implemented. In this case messages are expected to be in binary format. 53 | * `auth` Optional password for redis if the server is configured for it. 54 | * `select` Optionally select the db at connect. 55 | 56 | #### Usage 57 | 58 | Simple example: 59 | 60 | ```groovy 61 | def eb = vertx.eventBus() 62 | def config = new JsonObject() 63 | 64 | config.putString("address", address) 65 | config.putString("host", "localhost") 66 | config.putNumber("port", 6379) 67 | 68 | container.deployModule("io.vertx~mod-redis~1.1.5", config, 1) 69 | 70 | eb.send(address, [command: 'get', args: ['mykey']]) { reply -> 71 | if (reply.body.status.equals('ok') { 72 | // do something with reply.body.value 73 | } else { 74 | println('Error #{reply.body.message}') 75 | } 76 | } 77 | ``` 78 | 79 | Simple example with pub/sub mode: 80 | 81 | ```groovy 82 | def eb = vertx.eventBus() 83 | def pubConfig = new JsonObject() 84 | pubConfig.putString("address", 'redis.pub') 85 | def subConfig = new JsonObject() 86 | subConfig.putString("address", 'redis.sub') 87 | 88 | container.deployModule("io.vertx~mod-redis~1.1.5", pubConfig, 1) 89 | container.deployModule("io.vertx~mod-redis~1.1.5", subConfig, 1) 90 | 91 | // register a handler for the incoming message the naming the Redis module will use is base address + '.' + redis channel 92 | eb.registerHandler("redis.sub.ch1", new Handler>() { 93 | @Override 94 | void handle(Message received) { 95 | // do whatever you need to do with your message 96 | def value = received.body.getField('value') 97 | // the value is a JSON doc with the following properties 98 | // channel - The channel to which this message was sent 99 | // pattern - Pattern is present if you use psubscribe command and is the pattern that matched this message channel 100 | // message - The message payload 101 | } 102 | }); 103 | 104 | // on sub address subscribe to channel ch1 105 | eb.send('redis.sub', [command: 'subscribe', args: ['ch1']]) { subscribe -> 106 | } 107 | 108 | // on pub address publish a message 109 | eb.send('redis.pub', [command: 'publish', args: ['ch1', 'Hello World!']]) { publish -> 110 | } 111 | ``` 112 | 113 | 114 | ##### Sending Commands 115 | 116 | Each Redis command is exposed as a json document on the `EventBus`. All commands take a field `command` and a JsonArray 117 | of arguments as described on the main redis documentation site. 118 | 119 | An example would be: 120 | 121 | { 122 | command: "get", 123 | args: ["mykey"] 124 | } 125 | 126 | When the command completes successfuly the response would be: 127 | 128 | { 129 | status: "ok", 130 | "value": "the value stored on redis" 131 | } 132 | 133 | If an error occurs a reply is returned: 134 | 135 | { 136 | "status": "error", 137 | "message": 138 | } 139 | 140 | Where `message` is an error message. 141 | 142 | For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands) 143 | 144 | At the moment, commands can be specified only in lowercase. Minimal parsing is done on the replies. 145 | Commands that return a single line reply return `java.lang.String`, integer replies return `java.lang.Number`, 146 | "bulk" replies return an array of `java.lang.String` using the specified encoding, and "multi bulk" replies return a 147 | array of `java.lang.String` again using the specified encoding. `hgetall` is returns a `JsonObject`. 148 | 149 | #### Friendlier hash commands 150 | 151 | Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single 152 | String or an Array of Strings. When dealing with hash values, there are a couple of useful exceptions to this. 153 | 154 | ##### command hgetall 155 | 156 | The reply from an `hgetall` command will be converted into a JSON Object. That way you can interact with the responses 157 | using JSON syntax which is handy for the EventBus communication. 158 | 159 | ##### command mset 160 | 161 | Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings. 162 | 163 | { 164 | command: "mset", 165 | key: "redis key", 166 | keys: { 167 | keyName: "value", 168 | otherKeyName: "other value" 169 | } 170 | } 171 | 172 | ##### command msetnx 173 | 174 | Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings. 175 | 176 | { 177 | command: "msetnx", 178 | key: "redis key", 179 | keys: { 180 | keyName: "value", 181 | otherKeyName: "other value" 182 | } 183 | } 184 | 185 | ##### command hmset 186 | 187 | Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings. 188 | 189 | { 190 | command: "hmset", 191 | key: "redis key", 192 | fields: { 193 | fieldName: "value", 194 | otherFieldName: "other value" 195 | } 196 | } 197 | 198 | ##### command zadd 199 | 200 | Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings. 201 | 202 | { 203 | command: "zadd", 204 | key: "redis key", 205 | scores: { 206 | score: "member", 207 | otherScore: "other member" 208 | } 209 | } 210 | 211 | 212 | #### Pub/Sub 213 | 214 | As demonstrated with the source code example above, the module can work in pub/sub mode too. The basic idea behind it is 215 | that you need to register a new handler for the address: `mod-redis-io-address.your_real_redis_address` At this moment 216 | all commands to `subscribe`, `psubscribe`, `unsubscribe` and `punsubscribe` will send the received messages to the right 217 | address. 218 | 219 | The destination address is defined as a concatenation of the module address plus the redis address. This choice was made 220 | to keep the existing json to redis api as close as possible to the official documentation. For example lets say we have 221 | a module deployed at `mod.redis.pub` if we want to call the `[p]subscribe` method then first we should register an handler 222 | with the name of the redis channel/pattern we want to listen and then call the redis command. 223 | 224 | Seting up a subscription for a specific channel: 225 | 226 | ```java 227 | container.deployModule("io.vertx.mod-redis", new JsonObject().putString("address", "redis.subscription"), 1); 228 | 229 | // register a handler for the incoming message 230 | eb.registerHandler("redis.subscription.mychannel", new Handler>() { 231 | @Override 232 | void handle(Message received) { 233 | JsonObject value = received.body.getObject("value"); 234 | // the value is a JSON doc with the following properties 235 | // channel - The channel to which this message was sent 236 | // message - The message payload 237 | ... 238 | } 239 | }); 240 | 241 | // subscribe to channel mychannel 242 | eb.send("redis.sub", new JsonObject("{command: \"subscribe\", args: [\"mychannel\"]})); 243 | ``` 244 | 245 | Setting up a subscription to a pattern: 246 | 247 | ```java 248 | container.deployModule("io.vertx.mod-redis", new JsonObject().putString("address", "redis.subscription"), 1); 249 | 250 | // register a handler for the incoming message 251 | eb.registerHandler("redis.subscription.news.*", new Handler>() { 252 | @Override 253 | void handle(Message received) { 254 | JsonObject value = received.body.getObject("value"); 255 | // the value is a JSON doc with the following properties 256 | // channel - The channel to which this message was sent 257 | // pattern - Pattern is present if you use psubscribe command and is the pattern that matched this message channel 258 | // message - The message payload 259 | ... 260 | } 261 | }); 262 | 263 | // subscribe to channel mychannel 264 | eb.send("redis.sub", new JsonObject("{command: \"subscribe\", args: [\"news.*\]"})); 265 | ``` 266 | 267 | Note that in the last example that you can receive messages published both to `news.sports` and `news.world`. In order to 268 | know better wich destination the message had on the handler the received message contains the following format: 269 | 270 | { 271 | channel: "String with the absolute channel name", 272 | pattern: "String with the pattern that matched the channel and *only* present in psubscribe replies", 273 | message: "The actual message payload" 274 | } 275 | 276 | The fields `channel` and `message` are always present, however the field `pattern` is only present if you subscribed a 277 | channel with `psubscribe`. 278 | 279 | 280 | #### Monitor 281 | 282 | TODO: The module will do monitoring 283 | 284 | #### Server info 285 | 286 | The module converts the info response to a friendly Json 287 | 288 | { 289 | server: { 290 | redis_version: "2.5.13", 291 | redis_git_sha1: "2812b945", 292 | redis_git_dirty: "0", 293 | os: "Linux 2.6.32.16-linode28 i686", 294 | arch_bits: "32", 295 | multiplexing_api: "epoll", 296 | gcc_version: "4.4.1", 297 | process_id: "8107", 298 | ... 299 | }, 300 | memory: {...}, 301 | client: {...}, 302 | ... 303 | } 304 | 305 | In order to make it easier to work with the `info` response you don't need to parse the data yourself and the module will 306 | return it in a easy to understand JSON format. The format is as follows: A JSON object for each section filled with 307 | properties that belong to that section. If for some reason there is no section the properties will be visible at the top 308 | level object. 309 | 310 | #### Binary 311 | 312 | TODO: either using putBinary or other alternative... 313 | 314 | #### Transactions 315 | 316 | TODO: love or hate they must be supported! :) 317 | 318 | ### mod-redis-client 319 | 320 | When using the `mod-redis-client` you get an abstraction on top of the base module. This abstraction allows you to use 321 | one of the following programming languages: 322 | 323 | * java 324 | * groovy 325 | * javascript 326 | 327 | Since this is a non runnable module you need to include it in your verticle mod.json. 328 | 329 | #### java 330 | 331 | When using java you can deploy the module as: 332 | 333 | // create a new client 334 | RedisClient redis = new RedisClient(eventBus(), "my.redis.address"); 335 | // deploy a mod-redis module with the default config 336 | redis.deployModule(container()); 337 | 338 | // use the API 339 | redis.set("key", "value", new Handler>() { 340 | ... 341 | // handle your response 342 | }); 343 | 344 | You have all the redis commands as methods in the RedisClient class. 345 | 346 | #### groovy 347 | 348 | When using java you can deploy the module as: 349 | 350 | // create a new client 351 | RedisClient redis = new RedisClient(eventBus, "my.redis.address"); 352 | // deploy a mod-redis module with the default config 353 | redis.deployModule(container); 354 | 355 | // use the API 356 | redis.set("key", "value") { message -> 357 | ... 358 | // handle your response 359 | } 360 | 361 | You have all the redis commands as methods in the RedisClient class. 362 | 363 | #### javascript 364 | 365 | When using java you can deploy the module as: 366 | 367 | // create a new client 368 | var redis = require('redisClient')("my.redis.address"); 369 | // deploy a mod-redis module with the default config 370 | redis.deployModule(); 371 | 372 | // use the API 373 | redis.set("key", "value", function (message) { 374 | ... 375 | // handle your response 376 | }); 377 | 378 | You have all the redis commands as methods in the RedisClient object. 379 | -------------------------------------------------------------------------------- /mod/src/main/java/io/vertx/redis/RedisConnection.java: -------------------------------------------------------------------------------- 1 | package io.vertx.redis; 2 | 3 | import java.util.*; 4 | 5 | import io.vertx.redis.impl.RedisAsyncResult; 6 | import io.vertx.redis.impl.RedisSubscriptions; 7 | import io.vertx.redis.impl.MessageHandler; 8 | import io.vertx.redis.impl.ReplyHandler; 9 | import org.vertx.java.core.AsyncResult; 10 | import org.vertx.java.core.AsyncResultHandler; 11 | import org.vertx.java.core.Handler; 12 | import org.vertx.java.core.Vertx; 13 | import org.vertx.java.core.logging.Logger; 14 | import org.vertx.java.core.net.NetClient; 15 | import org.vertx.java.core.net.NetSocket; 16 | 17 | /** 18 | * Base class for Redis Vertx client. Generated client would use the facilties 19 | * in this class to implement typed commands. 20 | */ 21 | public class RedisConnection implements ReplyHandler { 22 | 23 | 24 | private final Vertx vertx; 25 | private final Logger logger; 26 | 27 | private final Queue> repliesQueue = new LinkedList<>(); 28 | private final Queue connectingQueue = new LinkedList<>(); 29 | 30 | private final RedisSubscriptions subscriptions; 31 | private NetSocket netSocket; 32 | 33 | private final String host; 34 | private final int port; 35 | private final String auth; 36 | private final int select; 37 | 38 | private static enum State { 39 | DISCONNECTED, 40 | CONNECTING, 41 | CONNECTED 42 | } 43 | 44 | private State state = State.DISCONNECTED; 45 | 46 | public RedisConnection(Vertx vertx, final Logger logger, String host, int port, String auth, int select, RedisSubscriptions subscriptions) { 47 | this.vertx = vertx; 48 | this.logger = logger; 49 | this.host = host; 50 | this.port = port; 51 | this.auth = auth; 52 | this.select = select; 53 | this.subscriptions = subscriptions; 54 | } 55 | 56 | private void doAuth(final Handler next) { 57 | if (auth != null) { 58 | Command command = new Command("auth", auth).setHandler(new Handler() { 59 | @Override 60 | public void handle(Reply reply) { 61 | switch (reply.type()) { 62 | case '-': 63 | logger.error(reply.toString()); 64 | netSocket.close(); 65 | break; 66 | case '+': 67 | // OK 68 | next.handle(null); 69 | break; 70 | default: 71 | throw new RuntimeException("Unexpected reply: " + reply.type() + ": " + reply.data()); 72 | } 73 | } 74 | }); 75 | 76 | send(command); 77 | } else { 78 | next.handle(null); 79 | } 80 | } 81 | 82 | private void doSelect(final Handler next) { 83 | if (select != 0) { 84 | Command command = new Command("select", select).setHandler(new Handler() { 85 | @Override 86 | public void handle(Reply reply) { 87 | switch (reply.type()) { 88 | case '-': 89 | logger.error(reply.toString()); 90 | netSocket.close(); 91 | break; 92 | case '+': 93 | // OK 94 | next.handle(null); 95 | break; 96 | default: 97 | throw new RuntimeException("Unexpected reply: " + reply.type() + ": " + reply.data()); 98 | } 99 | } 100 | }); 101 | 102 | send(command); 103 | } else { 104 | next.handle(null); 105 | } 106 | } 107 | 108 | private void onConnect(final Handler next) { 109 | doAuth(new Handler() { 110 | @Override 111 | public void handle(Void event) { 112 | doSelect(new Handler() { 113 | @Override 114 | public void handle(Void event) { 115 | next.handle(null); 116 | } 117 | }); 118 | } 119 | }); 120 | } 121 | 122 | void connect(final AsyncResultHandler resultHandler) { 123 | if (state == State.DISCONNECTED) { 124 | state = State.CONNECTING; 125 | // instantiate a parser for the connection 126 | final ReplyParser replyParser = new ReplyParser(this); 127 | 128 | NetClient client = vertx.createNetClient(); 129 | client.connect(port, host, new AsyncResultHandler() { 130 | @Override 131 | public void handle(final AsyncResult asyncResult) { 132 | if (asyncResult.failed()) { 133 | logger.error("Net client error", asyncResult.cause()); 134 | // clean the reply queue 135 | while (!repliesQueue.isEmpty()) { 136 | repliesQueue.poll().handle(new Reply('-', "Connection closed")); 137 | } 138 | // clean waiting for connection queue 139 | while (!connectingQueue.isEmpty()) { 140 | connectingQueue.poll().getHandler().handle(new Reply('-', "Connection closed")); 141 | } 142 | if (resultHandler != null) { 143 | resultHandler.handle(new RedisAsyncResult(asyncResult.cause())); 144 | } 145 | // make sure the socket is closed 146 | if (netSocket != null) { 147 | netSocket.close(); 148 | } 149 | // update state 150 | state = State.DISCONNECTED; 151 | } else { 152 | state = State.CONNECTED; 153 | netSocket = asyncResult.result(); 154 | // set the data handler (the reply parser) 155 | netSocket.dataHandler(replyParser); 156 | // set the exception handler 157 | netSocket.exceptionHandler(new Handler() { 158 | public void handle(Throwable e) { 159 | logger.error("Socket client error", e); 160 | // clean the reply queue 161 | while (!repliesQueue.isEmpty()) { 162 | repliesQueue.poll().handle(new Reply('-', "Connection closed")); 163 | } 164 | // clean waiting for connection queue 165 | while (!connectingQueue.isEmpty()) { 166 | connectingQueue.poll().getHandler().handle(new Reply('-', "Connection closed")); 167 | } 168 | // update state 169 | state = State.DISCONNECTED; 170 | } 171 | }); 172 | // set the close handler 173 | netSocket.closeHandler(new Handler() { 174 | public void handle(Void arg0) { 175 | logger.info("Socket closed"); 176 | // clean the reply queue 177 | while (!repliesQueue.isEmpty()) { 178 | repliesQueue.poll().handle(new Reply('-', "Connection closed")); 179 | } 180 | // clean waiting for connection queue 181 | while (!connectingQueue.isEmpty()) { 182 | connectingQueue.poll().getHandler().handle(new Reply('-', "Connection closed")); 183 | } 184 | // update state 185 | state = State.DISCONNECTED; 186 | } 187 | }); 188 | 189 | onConnect(new Handler() { 190 | @Override 191 | public void handle(Void event) { 192 | // process waiting queue (for messages that have been requested while the connection was not totally established) 193 | while (!connectingQueue.isEmpty()) { 194 | send(connectingQueue.poll()); 195 | } 196 | // emit ready! 197 | if (resultHandler != null) { 198 | resultHandler.handle(new RedisAsyncResult(null)); 199 | } 200 | } 201 | }); 202 | } 203 | } 204 | }); 205 | } 206 | } 207 | 208 | // Redis 'subscribe', 'unsubscribe', 'psubscribe' and 'punsubscribe' commands can have multiple (including zero) repliesQueue 209 | // See http://redis.io/topics/pubsub 210 | // In all cases we want to have a handler to report errors 211 | void send(final Command command) { 212 | switch (state) { 213 | case CONNECTED: 214 | // The order read must match the order written, vertx guarantees 215 | // that this is only called from a single thread. 216 | try { 217 | command.writeTo(netSocket); 218 | for (int i = 0; i < command.getExpectedReplies(); ++i) { 219 | repliesQueue.offer(command.getHandler()); 220 | } 221 | } catch (RuntimeException e) { 222 | // usually this means that the underlying socket is broken 223 | state = State.DISCONNECTED; 224 | // do not keep the client on hold forever, send an error back 225 | command.getHandler().handle(new Reply('-', e.getMessage())); 226 | } 227 | break; 228 | case DISCONNECTED: 229 | logger.info("Got request when disconnected. Trying to connect."); 230 | connect(new AsyncResultHandler() { 231 | public void handle(AsyncResult connection) { 232 | if (connection.succeeded()) { 233 | send(command); 234 | } else { 235 | command.getHandler().handle(new Reply('-', "Unable to connect")); 236 | } 237 | } 238 | }); 239 | break; 240 | case CONNECTING: 241 | logger.debug("Got send request while connecting. Will try again in a while."); 242 | connectingQueue.offer(command); 243 | } 244 | } 245 | 246 | @Override 247 | public void handleReply(Reply reply) { 248 | 249 | // Important to have this first - 'message' and 'pmessage' can be pushed at any moment, 250 | // so they must be filtered out before checking repliesQueue queue 251 | if (handlePushedPubSubMessage(reply)) { 252 | return; 253 | } 254 | 255 | Handler handler = repliesQueue.poll(); 256 | if (handler != null) { 257 | // handler waits for this response 258 | handler.handle(reply); 259 | return; 260 | } 261 | 262 | throw new RuntimeException("Received a non pub/sub message without reply handler waiting:"+reply.toString()); 263 | } 264 | 265 | // Handle 'message' and 'pmessage' messages; returns true if the message was handled 266 | // Appropriate number of handlers for 'subscribe', 'unsubscribe', 'psubscribe' and 'punsubscribe' is inserted when these commands are sent 267 | // See http://redis.io/topics/pubsub 268 | boolean handlePushedPubSubMessage(Reply reply) { 269 | // Pub/sub messages are always multi-bulk 270 | if (reply.is('*')) { 271 | Reply[] data = (Reply[]) reply.data(); 272 | if (data != null) { 273 | // message 274 | if (data.length == 3) { 275 | if (data[0].is('$') && "message".equals(data[0].toString("UTF-8"))) { 276 | String channel = data[1].toString("UTF-8"); 277 | MessageHandler handler = subscriptions.getChannelHandler(channel); 278 | if (handler != null) 279 | { 280 | handler.handle(channel, data); 281 | } 282 | // It is possible to get a message after removing subscription in the client but before Redis command executes, 283 | // so ignoring message here (consumer already is not interested in it) 284 | return true; 285 | } 286 | } 287 | // pmessage 288 | else if (data.length == 4) { 289 | if (data[0].is('$') && "pmessage".equals(data[0].toString("UTF-8"))) { 290 | String pattern = data[1].toString("UTF-8"); 291 | MessageHandler handler = subscriptions.getPatternHandler(pattern); 292 | if (handler != null) 293 | { 294 | handler.handle(pattern, data); 295 | } 296 | // It is possible to get a message after removing subscription in the client but before Redis command executes, 297 | // so ignoring message here (consumer already is not interested in it) 298 | return true; 299 | } 300 | } 301 | } 302 | } 303 | return false; 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /mod-client/src/main/groovy/io/vertx/groovy/redis/RedisClient.java: -------------------------------------------------------------------------------- 1 | package io.vertx.groovy.redis; 2 | 3 | import org.vertx.groovy.core.eventbus.EventBus; 4 | 5 | public class RedisClient extends AbstractRedisClient { 6 | 7 | public RedisClient(EventBus eventBus, String redisAddress) { 8 | super(eventBus, redisAddress); 9 | } 10 | 11 | /** 12 | * Get the values of all the given hash fields 13 | * @since 2.0.0 14 | */ 15 | public void hmget(Object... args) {send(RedisCommand.HMGET, args);} 16 | 17 | /** 18 | * Set multiple hash fields to multiple values 19 | * @since 2.0.0 20 | */ 21 | public void hmset(Object... args) {send(RedisCommand.HMSET, args);} 22 | 23 | /** 24 | * Determine the index of a member in a sorted set, with scores ordered from high to low 25 | * @since 2.0.0 26 | */ 27 | public void zrevrank(Object... args) {send(RedisCommand.ZREVRANK, args);} 28 | 29 | /** 30 | * Set the expiration for a key as a UNIX timestamp specified in milliseconds 31 | * @since 2.6.0 32 | */ 33 | public void pexpireat(Object... args) {send(RedisCommand.PEXPIREAT, args);} 34 | 35 | /** 36 | * Get the time to live for a key 37 | * @since 1.0.0 38 | */ 39 | public void ttl(Object... args) {send(RedisCommand.TTL, args);} 40 | 41 | /** 42 | * Check existence of scripts in the script cache. 43 | * @since 2.6.0 44 | */ 45 | public void script_exists(Object... args) {send(RedisCommand.SCRIPT_EXISTS, args);} 46 | 47 | /** 48 | * Intersect multiple sets and store the resulting set in a key 49 | * @since 1.0.0 50 | */ 51 | public void sinterstore(Object... args) {send(RedisCommand.SINTERSTORE, args);} 52 | 53 | /** 54 | * Get the UNIX time stamp of the last successful save to disk 55 | * @since 1.0.0 56 | */ 57 | public void lastsave(Object... args) {send(RedisCommand.LASTSAVE, args);} 58 | 59 | /** 60 | * Get the length of the value stored in a key 61 | * @since 2.2.0 62 | */ 63 | public void strlen(Object... args) {send(RedisCommand.STRLEN, args);} 64 | 65 | /** 66 | * Move a member from one set to another 67 | * @since 1.0.0 68 | */ 69 | public void smove(Object... args) {send(RedisCommand.SMOVE, args);} 70 | 71 | /** 72 | * Forget about all watched keys 73 | * @since 2.2.0 74 | */ 75 | public void unwatch(Object... args) {send(RedisCommand.UNWATCH, args);} 76 | 77 | /** 78 | * Determine the type stored at key 79 | * @since 1.0.0 80 | */ 81 | public void type(Object... args) {send(RedisCommand.TYPE, args);} 82 | 83 | /** 84 | * Add one or more members to a set 85 | * @since 1.0.0 86 | */ 87 | public void sadd(Object... args) {send(RedisCommand.SADD, args);} 88 | 89 | /** 90 | * Increment the integer value of a key by one 91 | * @since 1.0.0 92 | */ 93 | public void incr(Object... args) {send(RedisCommand.INCR, args);} 94 | 95 | /** 96 | * Count set bits in a string 97 | * @since 2.6.0 98 | */ 99 | public void bitcount(Object... args) {send(RedisCommand.BITCOUNT, args);} 100 | 101 | /** 102 | * Set the value of an element in a list by its index 103 | * @since 1.0.0 104 | */ 105 | public void lset(Object... args) {send(RedisCommand.LSET, args);} 106 | 107 | /** 108 | * Listen for all requests received by the server in real time 109 | * @since 1.0.0 110 | */ 111 | public void monitor(Object... args) {send(RedisCommand.MONITOR, args);} 112 | 113 | /** 114 | * Get the value of a key 115 | * @since 1.0.0 116 | */ 117 | public void get(Object... args) {send(RedisCommand.GET, args);} 118 | 119 | /** 120 | * Make the server crash 121 | * @since 1.0.0 122 | */ 123 | public void debug_segfault(Object... args) {send(RedisCommand.DEBUG_SEGFAULT, args);} 124 | 125 | /** 126 | * Append one or multiple values to a list 127 | * @since 1.0.0 128 | */ 129 | public void rpush(Object... args) {send(RedisCommand.RPUSH, args);} 130 | 131 | /** 132 | * Get a range of elements from a list 133 | * @since 1.0.0 134 | */ 135 | public void lrange(Object... args) {send(RedisCommand.LRANGE, args);} 136 | 137 | /** 138 | * Delete one or more hash fields 139 | * @since 2.0.0 140 | */ 141 | public void hdel(Object... args) {send(RedisCommand.HDEL, args);} 142 | 143 | /** 144 | * Merge N different HyperLogLogs into a single one. 145 | * @since 2.8.9 146 | */ 147 | public void pfmerge(Object... args) {send(RedisCommand.PFMERGE, args);} 148 | 149 | /** 150 | * Change the selected database for the current connection 151 | * @since 1.0.0 152 | */ 153 | public void select(Object... args) {send(RedisCommand.SELECT, args);} 154 | 155 | /** 156 | * Find first bit set or clear in a string 157 | * @since 2.8.7 158 | */ 159 | public void bitpos(Object... args) {send(RedisCommand.BITPOS, args);} 160 | 161 | /** 162 | * Inspect the state of the Pub/Sub subsystem 163 | * @since 2.8.0 164 | */ 165 | public void pubsub(Object... args) {send(RedisCommand.PUBSUB, args);} 166 | 167 | /** 168 | * Insert an element before or after another element in a list 169 | * @since 2.2.0 170 | */ 171 | public void linsert(Object... args) {send(RedisCommand.LINSERT, args);} 172 | 173 | /** 174 | * Adds the specified elements to the specified HyperLogLog. 175 | * @since 2.8.9 176 | */ 177 | public void pfadd(Object... args) {send(RedisCommand.PFADD, args);} 178 | 179 | /** 180 | * Pop a value from a list, push it to another list and return it; or block until one is available 181 | * @since 2.2.0 182 | */ 183 | public void brpoplpush(Object... args) {send(RedisCommand.BRPOPLPUSH, args);} 184 | 185 | /** 186 | * Trim a list to the specified range 187 | * @since 1.0.0 188 | */ 189 | public void ltrim(Object... args) {send(RedisCommand.LTRIM, args);} 190 | 191 | /** 192 | * Set multiple keys to multiple values 193 | * @since 1.0.1 194 | */ 195 | public void mset(Object... args) {send(RedisCommand.MSET, args);} 196 | 197 | /** 198 | * Create a key using the provided serialized value, previously obtained using DUMP. 199 | * @since 2.6.0 200 | */ 201 | public void restore(Object... args) {send(RedisCommand.RESTORE, args);} 202 | 203 | /** 204 | * Intersect multiple sets 205 | * @since 1.0.0 206 | */ 207 | public void sinter(Object... args) {send(RedisCommand.SINTER, args);} 208 | 209 | /** 210 | * Remove and get the last element in a list, or block until one is available 211 | * @since 2.0.0 212 | */ 213 | public void brpop(Object... args) {send(RedisCommand.BRPOP, args);} 214 | 215 | /** 216 | * Watch the given keys to determine execution of the MULTI/EXEC block 217 | * @since 2.2.0 218 | */ 219 | public void watch(Object... args) {send(RedisCommand.WATCH, args);} 220 | 221 | /** 222 | * Get the current connection name 223 | * @since 2.6.9 224 | */ 225 | public void client_getname(Object... args) {send(RedisCommand.CLIENT_GETNAME, args);} 226 | 227 | /** 228 | * Get the value of a configuration parameter 229 | * @since 2.0.0 230 | */ 231 | public void config_get(Object... args) {send(RedisCommand.CONFIG_GET, args);} 232 | 233 | /** 234 | * Get all the members in a set 235 | * @since 1.0.0 236 | */ 237 | public void smembers(Object... args) {send(RedisCommand.SMEMBERS, args);} 238 | 239 | /** 240 | * Set the value of a key, only if the key does not exist 241 | * @since 1.0.0 242 | */ 243 | public void setnx(Object... args) {send(RedisCommand.SETNX, args);} 244 | 245 | /** 246 | * Return a range of members in a sorted set, by score, with scores ordered from high to low 247 | * @since 2.2.0 248 | */ 249 | public void zrevrangebyscore(Object... args) {send(RedisCommand.ZREVRANGEBYSCORE, args);} 250 | 251 | /** 252 | * Increment the float value of a key by the given amount 253 | * @since 2.6.0 254 | */ 255 | public void incrbyfloat(Object... args) {send(RedisCommand.INCRBYFLOAT, args);} 256 | 257 | /** 258 | * Remove and return a random member from a set 259 | * @since 1.0.0 260 | */ 261 | public void spop(Object... args) {send(RedisCommand.SPOP, args);} 262 | 263 | /** 264 | * Get the number of fields in a hash 265 | * @since 2.0.0 266 | */ 267 | public void hlen(Object... args) {send(RedisCommand.HLEN, args);} 268 | 269 | /** 270 | * Make the server a slave of another instance, or promote it as master 271 | * @since 1.0.0 272 | */ 273 | public void slaveof(Object... args) {send(RedisCommand.SLAVEOF, args);} 274 | 275 | /** 276 | * Set the value and expiration in milliseconds of a key 277 | * @since 2.6.0 278 | */ 279 | public void psetex(Object... args) {send(RedisCommand.PSETEX, args);} 280 | 281 | /** 282 | * Set a key's time to live in seconds 283 | * @since 1.0.0 284 | */ 285 | public void expire(Object... args) {send(RedisCommand.EXPIRE, args);} 286 | 287 | /** 288 | * Decrement the integer value of a key by the given number 289 | * @since 1.0.0 290 | */ 291 | public void decrby(Object... args) {send(RedisCommand.DECRBY, args);} 292 | 293 | /** 294 | * Set multiple keys to multiple values, only if none of the keys exist 295 | * @since 1.0.1 296 | */ 297 | public void msetnx(Object... args) {send(RedisCommand.MSETNX, args);} 298 | 299 | /** 300 | * Ping the server 301 | * @since 1.0.0 302 | */ 303 | public void ping(Object... args) {send(RedisCommand.PING, args);} 304 | 305 | /** 306 | * Discard all commands issued after MULTI 307 | * @since 2.0.0 308 | */ 309 | public void discard(Object... args) {send(RedisCommand.DISCARD, args);} 310 | 311 | /** 312 | * Add multiple sorted sets and store the resulting sorted set in a new key 313 | * @since 2.0.0 314 | */ 315 | public void zunionstore(Object... args) {send(RedisCommand.ZUNIONSTORE, args);} 316 | 317 | /** 318 | * Execute a Lua script server side 319 | * @since 2.6.0 320 | */ 321 | public void eval(Object... args) {send(RedisCommand.EVAL, args);} 322 | 323 | /** 324 | * Return a range of members in a sorted set, by lexicographical range 325 | * @since 2.8.9 326 | */ 327 | public void zrangebylex(Object... args) {send(RedisCommand.ZRANGEBYLEX, args);} 328 | 329 | /** 330 | * Atomically transfer a key from a Redis instance to another one. 331 | * @since 2.6.0 332 | */ 333 | public void migrate(Object... args) {send(RedisCommand.MIGRATE, args);} 334 | 335 | /** 336 | * Remove all keys from the current database 337 | * @since 1.0.0 338 | */ 339 | public void flushdb(Object... args) {send(RedisCommand.FLUSHDB, args);} 340 | 341 | /** 342 | * Get the length of a list 343 | * @since 1.0.0 344 | */ 345 | public void llen(Object... args) {send(RedisCommand.LLEN, args);} 346 | 347 | /** 348 | * Synchronously save the dataset to disk and then shut down the server 349 | * @since 1.0.0 350 | */ 351 | public void shutdown(Object... args) {send(RedisCommand.SHUTDOWN, args);} 352 | 353 | /** 354 | * Get the time to live for a key in milliseconds 355 | * @since 2.6.0 356 | */ 357 | public void pttl(Object... args) {send(RedisCommand.PTTL, args);} 358 | 359 | /** 360 | * Get all the fields and values in a hash 361 | * @since 2.0.0 362 | */ 363 | public void hgetall(Object... args) {send(RedisCommand.HGETALL, args);} 364 | 365 | /** 366 | * Rewrite the configuration file with the in memory configuration 367 | * @since 2.8.0 368 | */ 369 | public void config_rewrite(Object... args) {send(RedisCommand.CONFIG_REWRITE, args);} 370 | 371 | /** 372 | * Remove one or more members from a sorted set 373 | * @since 1.2.0 374 | */ 375 | public void zrem(Object... args) {send(RedisCommand.ZREM, args);} 376 | 377 | /** 378 | * Perform bitwise operations between strings 379 | * @since 2.6.0 380 | */ 381 | public void bitop(Object... args) {send(RedisCommand.BITOP, args);} 382 | 383 | /** 384 | * Kill the script currently in execution. 385 | * @since 2.6.0 386 | */ 387 | public void script_kill(Object... args) {send(RedisCommand.SCRIPT_KILL, args);} 388 | 389 | /** 390 | * Add multiple sets 391 | * @since 1.0.0 392 | */ 393 | public void sunion(Object... args) {send(RedisCommand.SUNION, args);} 394 | 395 | /** 396 | * Rename a key 397 | * @since 1.0.0 398 | */ 399 | public void rename(Object... args) {send(RedisCommand.RENAME, args);} 400 | 401 | /** 402 | * Remove the last element in a list, append it to another list and return it 403 | * @since 1.2.0 404 | */ 405 | public void rpoplpush(Object... args) {send(RedisCommand.RPOPLPUSH, args);} 406 | 407 | /** 408 | * Return the number of keys in the selected database 409 | * @since 1.0.0 410 | */ 411 | public void dbsize(Object... args) {send(RedisCommand.DBSIZE, args);} 412 | 413 | /** 414 | * Append a value to a key 415 | * @since 2.0.0 416 | */ 417 | public void append(Object... args) {send(RedisCommand.APPEND, args);} 418 | 419 | /** 420 | * Delete a key 421 | * @since 1.0.0 422 | */ 423 | public void del(Object... args) {send(RedisCommand.DEL, args);} 424 | 425 | /** 426 | * Return a random key from the keyspace 427 | * @since 1.0.0 428 | */ 429 | public void randomkey(Object... args) {send(RedisCommand.RANDOMKEY, args);} 430 | 431 | /** 432 | * Kill the connection of a client 433 | * @since 2.4.0 434 | */ 435 | public void client_kill(Object... args) {send(RedisCommand.CLIENT_KILL, args);} 436 | 437 | /** 438 | * Get the value of a hash field 439 | * @since 2.0.0 440 | */ 441 | public void hget(Object... args) {send(RedisCommand.HGET, args);} 442 | 443 | /** 444 | * Remove one or more members from a set 445 | * @since 1.0.0 446 | */ 447 | public void srem(Object... args) {send(RedisCommand.SREM, args);} 448 | 449 | /** 450 | * Listen for messages published to the given channels 451 | * @since 2.0.0 452 | */ 453 | public void subscribe(Object... args) {send(RedisCommand.SUBSCRIBE, args);} 454 | 455 | /** 456 | * Incrementally iterate sorted sets elements and associated scores 457 | * @since 2.8.0 458 | */ 459 | public void zscan(Object... args) {send(RedisCommand.ZSCAN, args);} 460 | 461 | /** 462 | * Mark the start of a transaction block 463 | * @since 1.2.0 464 | */ 465 | public void multi(Object... args) {send(RedisCommand.MULTI, args);} 466 | 467 | /** 468 | * Set the string value of a hash field 469 | * @since 2.0.0 470 | */ 471 | public void hset(Object... args) {send(RedisCommand.HSET, args);} 472 | 473 | /** 474 | * Append a value to a list, only if the list exists 475 | * @since 2.2.0 476 | */ 477 | public void rpushx(Object... args) {send(RedisCommand.RPUSHX, args);} 478 | 479 | /** 480 | * Determine if a given value is a member of a set 481 | * @since 1.0.0 482 | */ 483 | public void sismember(Object... args) {send(RedisCommand.SISMEMBER, args);} 484 | 485 | /** 486 | * Sets or clears the bit at offset in the string value stored at key 487 | * @since 2.2.0 488 | */ 489 | public void setbit(Object... args) {send(RedisCommand.SETBIT, args);} 490 | 491 | /** 492 | * Close the connection 493 | * @since 1.0.0 494 | */ 495 | public void quit(Object... args) {send(RedisCommand.QUIT, args);} 496 | 497 | /** 498 | * Return the current server time 499 | * @since 2.6.0 500 | */ 501 | public void time(Object... args) {send(RedisCommand.TIME, args);} 502 | 503 | /** 504 | * Stop listening for messages posted to channels matching the given patterns 505 | * @since 2.0.0 506 | */ 507 | public void punsubscribe(Object... args) {send(RedisCommand.PUNSUBSCRIBE, args);} 508 | 509 | /** 510 | * Manages the Redis slow queries log 511 | * @since 2.2.12 512 | */ 513 | public void slowlog(Object... args) {send(RedisCommand.SLOWLOG, args);} 514 | 515 | /** 516 | * Increment the score of a member in a sorted set 517 | * @since 1.2.0 518 | */ 519 | public void zincrby(Object... args) {send(RedisCommand.ZINCRBY, args);} 520 | 521 | /** 522 | * Get the number of members in a set 523 | * @since 1.0.0 524 | */ 525 | public void scard(Object... args) {send(RedisCommand.SCARD, args);} 526 | 527 | /** 528 | * Authenticate to the server 529 | * @since 1.0.0 530 | */ 531 | public void auth(Object... args) {send(RedisCommand.AUTH, args);} 532 | 533 | /** 534 | * Inspect the internals of Redis objects 535 | * @since 2.2.3 536 | */ 537 | public void object(Object... args) {send(RedisCommand.OBJECT, args);} 538 | 539 | /** 540 | * Subtract multiple sets and store the resulting set in a key 541 | * @since 1.0.0 542 | */ 543 | public void sdiffstore(Object... args) {send(RedisCommand.SDIFFSTORE, args);} 544 | 545 | /** 546 | * Remove elements from a list 547 | * @since 1.0.0 548 | */ 549 | public void lrem(Object... args) {send(RedisCommand.LREM, args);} 550 | 551 | /** 552 | * Incrementally iterate the keys space 553 | * @since 2.8.0 554 | */ 555 | public void scan(Object... args) {send(RedisCommand.SCAN, args);} 556 | 557 | /** 558 | * Load the specified Lua script into the script cache. 559 | * @since 2.6.0 560 | */ 561 | public void script_load(Object... args) {send(RedisCommand.SCRIPT_LOAD, args);} 562 | 563 | /** 564 | * Return a serialized version of the value stored at the specified key. 565 | * @since 2.6.0 566 | */ 567 | public void dump(Object... args) {send(RedisCommand.DUMP, args);} 568 | 569 | /** 570 | * Stop listening for messages posted to the given channels 571 | * @since 2.0.0 572 | */ 573 | public void unsubscribe(Object... args) {send(RedisCommand.UNSUBSCRIBE, args);} 574 | 575 | /** 576 | * Intersect multiple sorted sets and store the resulting sorted set in a new key 577 | * @since 2.0.0 578 | */ 579 | public void zinterstore(Object... args) {send(RedisCommand.ZINTERSTORE, args);} 580 | 581 | /** 582 | * Return a range of members in a sorted set, by score 583 | * @since 1.0.5 584 | */ 585 | public void zrangebyscore(Object... args) {send(RedisCommand.ZRANGEBYSCORE, args);} 586 | 587 | /** 588 | * Get the values of all the given keys 589 | * @since 1.0.0 590 | */ 591 | public void mget(Object... args) {send(RedisCommand.MGET, args);} 592 | 593 | /** 594 | * Set the expiration for a key as a UNIX timestamp 595 | * @since 1.2.0 596 | */ 597 | public void expireat(Object... args) {send(RedisCommand.EXPIREAT, args);} 598 | 599 | /** 600 | * Remove all members in a sorted set within the given scores 601 | * @since 1.2.0 602 | */ 603 | public void zremrangebyscore(Object... args) {send(RedisCommand.ZREMRANGEBYSCORE, args);} 604 | 605 | /** 606 | * Determine the index of a member in a sorted set 607 | * @since 2.0.0 608 | */ 609 | public void zrank(Object... args) {send(RedisCommand.ZRANK, args);} 610 | 611 | /** 612 | * Determine if a key exists 613 | * @since 1.0.0 614 | */ 615 | public void exists(Object... args) {send(RedisCommand.EXISTS, args);} 616 | 617 | /** 618 | * Return a range of members in a sorted set, by index 619 | * @since 1.2.0 620 | */ 621 | public void zrange(Object... args) {send(RedisCommand.ZRANGE, args);} 622 | 623 | /** 624 | * Get a substring of the string stored at a key 625 | * @since 2.4.0 626 | */ 627 | public void getrange(Object... args) {send(RedisCommand.GETRANGE, args);} 628 | 629 | /** 630 | * Set the value and expiration of a key 631 | * @since 2.0.0 632 | */ 633 | public void setex(Object... args) {send(RedisCommand.SETEX, args);} 634 | 635 | /** 636 | * Get the number of members in a sorted set 637 | * @since 1.2.0 638 | */ 639 | public void zcard(Object... args) {send(RedisCommand.ZCARD, args);} 640 | 641 | /** 642 | * Reset the stats returned by INFO 643 | * @since 2.0.0 644 | */ 645 | public void config_resetstat(Object... args) {send(RedisCommand.CONFIG_RESETSTAT, args);} 646 | 647 | /** 648 | * Return a range of members in a sorted set, by index, with scores ordered from high to low 649 | * @since 1.2.0 650 | */ 651 | public void zrevrange(Object... args) {send(RedisCommand.ZREVRANGE, args);} 652 | 653 | /** 654 | * Remove and get the first element in a list, or block until one is available 655 | * @since 2.0.0 656 | */ 657 | public void blpop(Object... args) {send(RedisCommand.BLPOP, args);} 658 | 659 | /** 660 | * Add one or more members to a sorted set, or update its score if it already exists 661 | * @since 1.2.0 662 | */ 663 | public void zadd(Object... args) {send(RedisCommand.ZADD, args);} 664 | 665 | /** 666 | * Subtract multiple sets 667 | * @since 1.0.0 668 | */ 669 | public void sdiff(Object... args) {send(RedisCommand.SDIFF, args);} 670 | 671 | /** 672 | * Increment the float value of a hash field by the given amount 673 | * @since 2.6.0 674 | */ 675 | public void hincrbyfloat(Object... args) {send(RedisCommand.HINCRBYFLOAT, args);} 676 | 677 | /** 678 | * Determine if a hash field exists 679 | * @since 2.0.0 680 | */ 681 | public void hexists(Object... args) {send(RedisCommand.HEXISTS, args);} 682 | 683 | /** 684 | * Asynchronously rewrite the append-only file 685 | * @since 1.0.0 686 | */ 687 | public void bgrewriteaof(Object... args) {send(RedisCommand.BGREWRITEAOF, args);} 688 | 689 | /** 690 | * Internal command used for replication 691 | * @since 1.0.0 692 | */ 693 | public void sync(Object... args) {send(RedisCommand.SYNC, args);} 694 | 695 | /** 696 | * Count the number of members in a sorted set between a given lexicographical range 697 | * @since 2.8.9 698 | */ 699 | public void zlexcount(Object... args) {send(RedisCommand.ZLEXCOUNT, args);} 700 | 701 | /** 702 | * Set the string value of a key and return its old value 703 | * @since 1.0.0 704 | */ 705 | public void getset(Object... args) {send(RedisCommand.GETSET, args);} 706 | 707 | /** 708 | * Remove all keys from all databases 709 | * @since 1.0.0 710 | */ 711 | public void flushall(Object... args) {send(RedisCommand.FLUSHALL, args);} 712 | 713 | /** 714 | * Rename a key, only if the new key does not exist 715 | * @since 1.0.0 716 | */ 717 | public void renamenx(Object... args) {send(RedisCommand.RENAMENX, args);} 718 | 719 | /** 720 | * Add multiple sets and store the resulting set in a key 721 | * @since 1.0.0 722 | */ 723 | public void sunionstore(Object... args) {send(RedisCommand.SUNIONSTORE, args);} 724 | 725 | /** 726 | * Incrementally iterate hash fields and associated values 727 | * @since 2.8.0 728 | */ 729 | public void hscan(Object... args) {send(RedisCommand.HSCAN, args);} 730 | 731 | /** 732 | * Sort the elements in a list, set or sorted set 733 | * @since 1.0.0 734 | */ 735 | public void sort(Object... args) {send(RedisCommand.SORT, args);} 736 | 737 | /** 738 | * Get the score associated with the given member in a sorted set 739 | * @since 1.2.0 740 | */ 741 | public void zscore(Object... args) {send(RedisCommand.ZSCORE, args);} 742 | 743 | /** 744 | * Set the string value of a key 745 | * @since 1.0.0 746 | */ 747 | public void set(Object... args) {send(RedisCommand.SET, args);} 748 | 749 | /** 750 | * Synchronously save the dataset to disk 751 | * @since 1.0.0 752 | */ 753 | public void save(Object... args) {send(RedisCommand.SAVE, args);} 754 | 755 | /** 756 | * Execute all commands issued after MULTI 757 | * @since 1.2.0 758 | */ 759 | public void exec(Object... args) {send(RedisCommand.EXEC, args);} 760 | 761 | /** 762 | * Increment the integer value of a hash field by the given number 763 | * @since 2.0.0 764 | */ 765 | public void hincrby(Object... args) {send(RedisCommand.HINCRBY, args);} 766 | 767 | /** 768 | * Get all the fields in a hash 769 | * @since 2.0.0 770 | */ 771 | public void hkeys(Object... args) {send(RedisCommand.HKEYS, args);} 772 | 773 | /** 774 | * Get one or multiple random members from a set 775 | * @since 1.0.0 776 | */ 777 | public void srandmember(Object... args) {send(RedisCommand.SRANDMEMBER, args);} 778 | 779 | /** 780 | * Incrementally iterate Set elements 781 | * @since 2.8.0 782 | */ 783 | public void sscan(Object... args) {send(RedisCommand.SSCAN, args);} 784 | 785 | /** 786 | * Get an element from a list by its index 787 | * @since 1.0.0 788 | */ 789 | public void lindex(Object... args) {send(RedisCommand.LINDEX, args);} 790 | 791 | /** 792 | * Increment the integer value of a key by the given amount 793 | * @since 1.0.0 794 | */ 795 | public void incrby(Object... args) {send(RedisCommand.INCRBY, args);} 796 | 797 | /** 798 | * Get information and statistics about the server 799 | * @since 1.0.0 800 | */ 801 | public void info(Object... args) {send(RedisCommand.INFO, args);} 802 | 803 | /** 804 | * Remove all members in a sorted set within the given indexes 805 | * @since 2.0.0 806 | */ 807 | public void zremrangebyrank(Object... args) {send(RedisCommand.ZREMRANGEBYRANK, args);} 808 | 809 | /** 810 | * Count the members in a sorted set with scores within the given values 811 | * @since 2.0.0 812 | */ 813 | public void zcount(Object... args) {send(RedisCommand.ZCOUNT, args);} 814 | 815 | /** 816 | * Overwrite part of a string at key starting at the specified offset 817 | * @since 2.2.0 818 | */ 819 | public void setrange(Object... args) {send(RedisCommand.SETRANGE, args);} 820 | 821 | /** 822 | * Remove and get the first element in a list 823 | * @since 1.0.0 824 | */ 825 | public void lpop(Object... args) {send(RedisCommand.LPOP, args);} 826 | 827 | /** 828 | * Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s). 829 | * @since 2.8.9 830 | */ 831 | public void pfcount(Object... args) {send(RedisCommand.PFCOUNT, args);} 832 | 833 | /** 834 | * Listen for messages published to channels matching the given patterns 835 | * @since 2.0.0 836 | */ 837 | public void psubscribe(Object... args) {send(RedisCommand.PSUBSCRIBE, args);} 838 | 839 | /** 840 | * Echo the given string 841 | * @since 1.0.0 842 | */ 843 | public void echo(Object... args) {send(RedisCommand.ECHO, args);} 844 | 845 | /** 846 | * Asynchronously save the dataset to disk 847 | * @since 1.0.0 848 | */ 849 | public void bgsave(Object... args) {send(RedisCommand.BGSAVE, args);} 850 | 851 | /** 852 | * Execute a Lua script server side 853 | * @since 2.6.0 854 | */ 855 | public void evalsha(Object... args) {send(RedisCommand.EVALSHA, args);} 856 | 857 | /** 858 | * Prepend one or multiple values to a list 859 | * @since 1.0.0 860 | */ 861 | public void lpush(Object... args) {send(RedisCommand.LPUSH, args);} 862 | 863 | /** 864 | * Remove the expiration from a key 865 | * @since 2.2.0 866 | */ 867 | public void persist(Object... args) {send(RedisCommand.PERSIST, args);} 868 | 869 | /** 870 | * Set a key's time to live in milliseconds 871 | * @since 2.6.0 872 | */ 873 | public void pexpire(Object... args) {send(RedisCommand.PEXPIRE, args);} 874 | 875 | /** 876 | * Stop processing commands from clients for some time 877 | * @since 2.9.50 878 | */ 879 | public void client_pause(Object... args) {send(RedisCommand.CLIENT_PAUSE, args);} 880 | 881 | /** 882 | * Remove and get the last element in a list 883 | * @since 1.0.0 884 | */ 885 | public void rpop(Object... args) {send(RedisCommand.RPOP, args);} 886 | 887 | /** 888 | * Move a key to another database 889 | * @since 1.0.0 890 | */ 891 | public void move(Object... args) {send(RedisCommand.MOVE, args);} 892 | 893 | /** 894 | * Prepend a value to a list, only if the list exists 895 | * @since 2.2.0 896 | */ 897 | public void lpushx(Object... args) {send(RedisCommand.LPUSHX, args);} 898 | 899 | /** 900 | * Decrement the integer value of a key by one 901 | * @since 1.0.0 902 | */ 903 | public void decr(Object... args) {send(RedisCommand.DECR, args);} 904 | 905 | /** 906 | * Get all the values in a hash 907 | * @since 2.0.0 908 | */ 909 | public void hvals(Object... args) {send(RedisCommand.HVALS, args);} 910 | 911 | /** 912 | * Set a configuration parameter to the given value 913 | * @since 2.0.0 914 | */ 915 | public void config_set(Object... args) {send(RedisCommand.CONFIG_SET, args);} 916 | 917 | /** 918 | * Find all keys matching the given pattern 919 | * @since 1.0.0 920 | */ 921 | public void keys(Object... args) {send(RedisCommand.KEYS, args);} 922 | 923 | /** 924 | * Set the value of a hash field, only if the field does not exist 925 | * @since 2.0.0 926 | */ 927 | public void hsetnx(Object... args) {send(RedisCommand.HSETNX, args);} 928 | 929 | /** 930 | * Returns the bit value at offset in the string value stored at key 931 | * @since 2.2.0 932 | */ 933 | public void getbit(Object... args) {send(RedisCommand.GETBIT, args);} 934 | 935 | /** 936 | * Get the list of client connections 937 | * @since 2.4.0 938 | */ 939 | public void client_list(Object... args) {send(RedisCommand.CLIENT_LIST, args);} 940 | 941 | /** 942 | * Set the current connection name 943 | * @since 2.6.9 944 | */ 945 | public void client_setname(Object... args) {send(RedisCommand.CLIENT_SETNAME, args);} 946 | 947 | /** 948 | * Post a message to a channel 949 | * @since 2.0.0 950 | */ 951 | public void publish(Object... args) {send(RedisCommand.PUBLISH, args);} 952 | 953 | /** 954 | * Remove all members in a sorted set between the given lexicographical range 955 | * @since 2.8.9 956 | */ 957 | public void zremrangebylex(Object... args) {send(RedisCommand.ZREMRANGEBYLEX, args);} 958 | 959 | /** 960 | * Remove all the scripts from the script cache. 961 | * @since 2.6.0 962 | */ 963 | public void script_flush(Object... args) {send(RedisCommand.SCRIPT_FLUSH, args);} 964 | 965 | /** 966 | * Get debugging information about a key 967 | * @since 1.0.0 968 | */ 969 | public void debug_object(Object... args) {send(RedisCommand.DEBUG_OBJECT, args);} 970 | } -------------------------------------------------------------------------------- /mod-client/src/main/java/io/vertx/java/redis/RedisClient.java: -------------------------------------------------------------------------------- 1 | package io.vertx.java.redis; 2 | 3 | import org.vertx.java.core.eventbus.EventBus; 4 | 5 | public class RedisClient extends AbstractRedisClient { 6 | 7 | public RedisClient(EventBus eventBus, String redisAddress) { 8 | super(eventBus, redisAddress); 9 | } 10 | 11 | /** 12 | * Get the values of all the given hash fields 13 | * @since 2.0.0 14 | */ 15 | public void hmget(Object... args) {send(RedisCommand.HMGET, args);} 16 | 17 | /** 18 | * Set multiple hash fields to multiple values 19 | * @since 2.0.0 20 | */ 21 | public void hmset(Object... args) {send(RedisCommand.HMSET, args);} 22 | 23 | /** 24 | * Determine the index of a member in a sorted set, with scores ordered from high to low 25 | * @since 2.0.0 26 | */ 27 | public void zrevrank(Object... args) {send(RedisCommand.ZREVRANK, args);} 28 | 29 | /** 30 | * Set the expiration for a key as a UNIX timestamp specified in milliseconds 31 | * @since 2.6.0 32 | */ 33 | public void pexpireat(Object... args) {send(RedisCommand.PEXPIREAT, args);} 34 | 35 | /** 36 | * Get the time to live for a key 37 | * @since 1.0.0 38 | */ 39 | public void ttl(Object... args) {send(RedisCommand.TTL, args);} 40 | 41 | /** 42 | * Check existence of scripts in the script cache. 43 | * @since 2.6.0 44 | */ 45 | public void script_exists(Object... args) {send(RedisCommand.SCRIPT_EXISTS, args);} 46 | 47 | /** 48 | * Intersect multiple sets and store the resulting set in a key 49 | * @since 1.0.0 50 | */ 51 | public void sinterstore(Object... args) {send(RedisCommand.SINTERSTORE, args);} 52 | 53 | /** 54 | * Get the UNIX time stamp of the last successful save to disk 55 | * @since 1.0.0 56 | */ 57 | public void lastsave(Object... args) {send(RedisCommand.LASTSAVE, args);} 58 | 59 | /** 60 | * Get the length of the value stored in a key 61 | * @since 2.2.0 62 | */ 63 | public void strlen(Object... args) {send(RedisCommand.STRLEN, args);} 64 | 65 | /** 66 | * Move a member from one set to another 67 | * @since 1.0.0 68 | */ 69 | public void smove(Object... args) {send(RedisCommand.SMOVE, args);} 70 | 71 | /** 72 | * Forget about all watched keys 73 | * @since 2.2.0 74 | */ 75 | public void unwatch(Object... args) {send(RedisCommand.UNWATCH, args);} 76 | 77 | /** 78 | * Determine the type stored at key 79 | * @since 1.0.0 80 | */ 81 | public void type(Object... args) {send(RedisCommand.TYPE, args);} 82 | 83 | /** 84 | * Add one or more members to a set 85 | * @since 1.0.0 86 | */ 87 | public void sadd(Object... args) {send(RedisCommand.SADD, args);} 88 | 89 | /** 90 | * Increment the integer value of a key by one 91 | * @since 1.0.0 92 | */ 93 | public void incr(Object... args) {send(RedisCommand.INCR, args);} 94 | 95 | /** 96 | * Count set bits in a string 97 | * @since 2.6.0 98 | */ 99 | public void bitcount(Object... args) {send(RedisCommand.BITCOUNT, args);} 100 | 101 | /** 102 | * Set the value of an element in a list by its index 103 | * @since 1.0.0 104 | */ 105 | public void lset(Object... args) {send(RedisCommand.LSET, args);} 106 | 107 | /** 108 | * Listen for all requests received by the server in real time 109 | * @since 1.0.0 110 | */ 111 | public void monitor(Object... args) {send(RedisCommand.MONITOR, args);} 112 | 113 | /** 114 | * Get the value of a key 115 | * @since 1.0.0 116 | */ 117 | public void get(Object... args) {send(RedisCommand.GET, args);} 118 | 119 | /** 120 | * Make the server crash 121 | * @since 1.0.0 122 | */ 123 | public void debug_segfault(Object... args) {send(RedisCommand.DEBUG_SEGFAULT, args);} 124 | 125 | /** 126 | * Append one or multiple values to a list 127 | * @since 1.0.0 128 | */ 129 | public void rpush(Object... args) {send(RedisCommand.RPUSH, args);} 130 | 131 | /** 132 | * Get a range of elements from a list 133 | * @since 1.0.0 134 | */ 135 | public void lrange(Object... args) {send(RedisCommand.LRANGE, args);} 136 | 137 | /** 138 | * Delete one or more hash fields 139 | * @since 2.0.0 140 | */ 141 | public void hdel(Object... args) {send(RedisCommand.HDEL, args);} 142 | 143 | /** 144 | * Merge N different HyperLogLogs into a single one. 145 | * @since 2.8.9 146 | */ 147 | public void pfmerge(Object... args) {send(RedisCommand.PFMERGE, args);} 148 | 149 | /** 150 | * Change the selected database for the current connection 151 | * @since 1.0.0 152 | */ 153 | public void select(Object... args) {send(RedisCommand.SELECT, args);} 154 | 155 | /** 156 | * Find first bit set or clear in a string 157 | * @since 2.8.7 158 | */ 159 | public void bitpos(Object... args) {send(RedisCommand.BITPOS, args);} 160 | 161 | /** 162 | * Inspect the state of the Pub/Sub subsystem 163 | * @since 2.8.0 164 | */ 165 | public void pubsub(Object... args) {send(RedisCommand.PUBSUB, args);} 166 | 167 | /** 168 | * Insert an element before or after another element in a list 169 | * @since 2.2.0 170 | */ 171 | public void linsert(Object... args) {send(RedisCommand.LINSERT, args);} 172 | 173 | /** 174 | * Adds the specified elements to the specified HyperLogLog. 175 | * @since 2.8.9 176 | */ 177 | public void pfadd(Object... args) {send(RedisCommand.PFADD, args);} 178 | 179 | /** 180 | * Pop a value from a list, push it to another list and return it; or block until one is available 181 | * @since 2.2.0 182 | */ 183 | public void brpoplpush(Object... args) {send(RedisCommand.BRPOPLPUSH, args);} 184 | 185 | /** 186 | * Trim a list to the specified range 187 | * @since 1.0.0 188 | */ 189 | public void ltrim(Object... args) {send(RedisCommand.LTRIM, args);} 190 | 191 | /** 192 | * Set multiple keys to multiple values 193 | * @since 1.0.1 194 | */ 195 | public void mset(Object... args) {send(RedisCommand.MSET, args);} 196 | 197 | /** 198 | * Create a key using the provided serialized value, previously obtained using DUMP. 199 | * @since 2.6.0 200 | */ 201 | public void restore(Object... args) {send(RedisCommand.RESTORE, args);} 202 | 203 | /** 204 | * Intersect multiple sets 205 | * @since 1.0.0 206 | */ 207 | public void sinter(Object... args) {send(RedisCommand.SINTER, args);} 208 | 209 | /** 210 | * Remove and get the last element in a list, or block until one is available 211 | * @since 2.0.0 212 | */ 213 | public void brpop(Object... args) {send(RedisCommand.BRPOP, args);} 214 | 215 | /** 216 | * Watch the given keys to determine execution of the MULTI/EXEC block 217 | * @since 2.2.0 218 | */ 219 | public void watch(Object... args) {send(RedisCommand.WATCH, args);} 220 | 221 | /** 222 | * Get the current connection name 223 | * @since 2.6.9 224 | */ 225 | public void client_getname(Object... args) {send(RedisCommand.CLIENT_GETNAME, args);} 226 | 227 | /** 228 | * Get the value of a configuration parameter 229 | * @since 2.0.0 230 | */ 231 | public void config_get(Object... args) {send(RedisCommand.CONFIG_GET, args);} 232 | 233 | /** 234 | * Get all the members in a set 235 | * @since 1.0.0 236 | */ 237 | public void smembers(Object... args) {send(RedisCommand.SMEMBERS, args);} 238 | 239 | /** 240 | * Set the value of a key, only if the key does not exist 241 | * @since 1.0.0 242 | */ 243 | public void setnx(Object... args) {send(RedisCommand.SETNX, args);} 244 | 245 | /** 246 | * Return a range of members in a sorted set, by score, with scores ordered from high to low 247 | * @since 2.2.0 248 | */ 249 | public void zrevrangebyscore(Object... args) {send(RedisCommand.ZREVRANGEBYSCORE, args);} 250 | 251 | /** 252 | * Increment the float value of a key by the given amount 253 | * @since 2.6.0 254 | */ 255 | public void incrbyfloat(Object... args) {send(RedisCommand.INCRBYFLOAT, args);} 256 | 257 | /** 258 | * Remove and return a random member from a set 259 | * @since 1.0.0 260 | */ 261 | public void spop(Object... args) {send(RedisCommand.SPOP, args);} 262 | 263 | /** 264 | * Get the number of fields in a hash 265 | * @since 2.0.0 266 | */ 267 | public void hlen(Object... args) {send(RedisCommand.HLEN, args);} 268 | 269 | /** 270 | * Make the server a slave of another instance, or promote it as master 271 | * @since 1.0.0 272 | */ 273 | public void slaveof(Object... args) {send(RedisCommand.SLAVEOF, args);} 274 | 275 | /** 276 | * Set the value and expiration in milliseconds of a key 277 | * @since 2.6.0 278 | */ 279 | public void psetex(Object... args) {send(RedisCommand.PSETEX, args);} 280 | 281 | /** 282 | * Set a key's time to live in seconds 283 | * @since 1.0.0 284 | */ 285 | public void expire(Object... args) {send(RedisCommand.EXPIRE, args);} 286 | 287 | /** 288 | * Decrement the integer value of a key by the given number 289 | * @since 1.0.0 290 | */ 291 | public void decrby(Object... args) {send(RedisCommand.DECRBY, args);} 292 | 293 | /** 294 | * Set multiple keys to multiple values, only if none of the keys exist 295 | * @since 1.0.1 296 | */ 297 | public void msetnx(Object... args) {send(RedisCommand.MSETNX, args);} 298 | 299 | /** 300 | * Ping the server 301 | * @since 1.0.0 302 | */ 303 | public void ping(Object... args) {send(RedisCommand.PING, args);} 304 | 305 | /** 306 | * Discard all commands issued after MULTI 307 | * @since 2.0.0 308 | */ 309 | public void discard(Object... args) {send(RedisCommand.DISCARD, args);} 310 | 311 | /** 312 | * Add multiple sorted sets and store the resulting sorted set in a new key 313 | * @since 2.0.0 314 | */ 315 | public void zunionstore(Object... args) {send(RedisCommand.ZUNIONSTORE, args);} 316 | 317 | /** 318 | * Execute a Lua script server side 319 | * @since 2.6.0 320 | */ 321 | public void eval(Object... args) {send(RedisCommand.EVAL, args);} 322 | 323 | /** 324 | * Return a range of members in a sorted set, by lexicographical range 325 | * @since 2.8.9 326 | */ 327 | public void zrangebylex(Object... args) {send(RedisCommand.ZRANGEBYLEX, args);} 328 | 329 | /** 330 | * Atomically transfer a key from a Redis instance to another one. 331 | * @since 2.6.0 332 | */ 333 | public void migrate(Object... args) {send(RedisCommand.MIGRATE, args);} 334 | 335 | /** 336 | * Remove all keys from the current database 337 | * @since 1.0.0 338 | */ 339 | public void flushdb(Object... args) {send(RedisCommand.FLUSHDB, args);} 340 | 341 | /** 342 | * Get the length of a list 343 | * @since 1.0.0 344 | */ 345 | public void llen(Object... args) {send(RedisCommand.LLEN, args);} 346 | 347 | /** 348 | * Synchronously save the dataset to disk and then shut down the server 349 | * @since 1.0.0 350 | */ 351 | public void shutdown(Object... args) {send(RedisCommand.SHUTDOWN, args);} 352 | 353 | /** 354 | * Get the time to live for a key in milliseconds 355 | * @since 2.6.0 356 | */ 357 | public void pttl(Object... args) {send(RedisCommand.PTTL, args);} 358 | 359 | /** 360 | * Get all the fields and values in a hash 361 | * @since 2.0.0 362 | */ 363 | public void hgetall(Object... args) {send(RedisCommand.HGETALL, args);} 364 | 365 | /** 366 | * Rewrite the configuration file with the in memory configuration 367 | * @since 2.8.0 368 | */ 369 | public void config_rewrite(Object... args) {send(RedisCommand.CONFIG_REWRITE, args);} 370 | 371 | /** 372 | * Remove one or more members from a sorted set 373 | * @since 1.2.0 374 | */ 375 | public void zrem(Object... args) {send(RedisCommand.ZREM, args);} 376 | 377 | /** 378 | * Perform bitwise operations between strings 379 | * @since 2.6.0 380 | */ 381 | public void bitop(Object... args) {send(RedisCommand.BITOP, args);} 382 | 383 | /** 384 | * Kill the script currently in execution. 385 | * @since 2.6.0 386 | */ 387 | public void script_kill(Object... args) {send(RedisCommand.SCRIPT_KILL, args);} 388 | 389 | /** 390 | * Add multiple sets 391 | * @since 1.0.0 392 | */ 393 | public void sunion(Object... args) {send(RedisCommand.SUNION, args);} 394 | 395 | /** 396 | * Rename a key 397 | * @since 1.0.0 398 | */ 399 | public void rename(Object... args) {send(RedisCommand.RENAME, args);} 400 | 401 | /** 402 | * Remove the last element in a list, append it to another list and return it 403 | * @since 1.2.0 404 | */ 405 | public void rpoplpush(Object... args) {send(RedisCommand.RPOPLPUSH, args);} 406 | 407 | /** 408 | * Return the number of keys in the selected database 409 | * @since 1.0.0 410 | */ 411 | public void dbsize(Object... args) {send(RedisCommand.DBSIZE, args);} 412 | 413 | /** 414 | * Append a value to a key 415 | * @since 2.0.0 416 | */ 417 | public void append(Object... args) {send(RedisCommand.APPEND, args);} 418 | 419 | /** 420 | * Delete a key 421 | * @since 1.0.0 422 | */ 423 | public void del(Object... args) {send(RedisCommand.DEL, args);} 424 | 425 | /** 426 | * Return a random key from the keyspace 427 | * @since 1.0.0 428 | */ 429 | public void randomkey(Object... args) {send(RedisCommand.RANDOMKEY, args);} 430 | 431 | /** 432 | * Kill the connection of a client 433 | * @since 2.4.0 434 | */ 435 | public void client_kill(Object... args) {send(RedisCommand.CLIENT_KILL, args);} 436 | 437 | /** 438 | * Get the value of a hash field 439 | * @since 2.0.0 440 | */ 441 | public void hget(Object... args) {send(RedisCommand.HGET, args);} 442 | 443 | /** 444 | * Remove one or more members from a set 445 | * @since 1.0.0 446 | */ 447 | public void srem(Object... args) {send(RedisCommand.SREM, args);} 448 | 449 | /** 450 | * Listen for messages published to the given channels 451 | * @since 2.0.0 452 | */ 453 | public void subscribe(Object... args) {send(RedisCommand.SUBSCRIBE, args);} 454 | 455 | /** 456 | * Incrementally iterate sorted sets elements and associated scores 457 | * @since 2.8.0 458 | */ 459 | public void zscan(Object... args) {send(RedisCommand.ZSCAN, args);} 460 | 461 | /** 462 | * Mark the start of a transaction block 463 | * @since 1.2.0 464 | */ 465 | public void multi(Object... args) {send(RedisCommand.MULTI, args);} 466 | 467 | /** 468 | * Set the string value of a hash field 469 | * @since 2.0.0 470 | */ 471 | public void hset(Object... args) {send(RedisCommand.HSET, args);} 472 | 473 | /** 474 | * Append a value to a list, only if the list exists 475 | * @since 2.2.0 476 | */ 477 | public void rpushx(Object... args) {send(RedisCommand.RPUSHX, args);} 478 | 479 | /** 480 | * Determine if a given value is a member of a set 481 | * @since 1.0.0 482 | */ 483 | public void sismember(Object... args) {send(RedisCommand.SISMEMBER, args);} 484 | 485 | /** 486 | * Sets or clears the bit at offset in the string value stored at key 487 | * @since 2.2.0 488 | */ 489 | public void setbit(Object... args) {send(RedisCommand.SETBIT, args);} 490 | 491 | /** 492 | * Close the connection 493 | * @since 1.0.0 494 | */ 495 | public void quit(Object... args) {send(RedisCommand.QUIT, args);} 496 | 497 | /** 498 | * Return the current server time 499 | * @since 2.6.0 500 | */ 501 | public void time(Object... args) {send(RedisCommand.TIME, args);} 502 | 503 | /** 504 | * Stop listening for messages posted to channels matching the given patterns 505 | * @since 2.0.0 506 | */ 507 | public void punsubscribe(Object... args) {send(RedisCommand.PUNSUBSCRIBE, args);} 508 | 509 | /** 510 | * Manages the Redis slow queries log 511 | * @since 2.2.12 512 | */ 513 | public void slowlog(Object... args) {send(RedisCommand.SLOWLOG, args);} 514 | 515 | /** 516 | * Increment the score of a member in a sorted set 517 | * @since 1.2.0 518 | */ 519 | public void zincrby(Object... args) {send(RedisCommand.ZINCRBY, args);} 520 | 521 | /** 522 | * Get the number of members in a set 523 | * @since 1.0.0 524 | */ 525 | public void scard(Object... args) {send(RedisCommand.SCARD, args);} 526 | 527 | /** 528 | * Authenticate to the server 529 | * @since 1.0.0 530 | */ 531 | public void auth(Object... args) {send(RedisCommand.AUTH, args);} 532 | 533 | /** 534 | * Inspect the internals of Redis objects 535 | * @since 2.2.3 536 | */ 537 | public void object(Object... args) {send(RedisCommand.OBJECT, args);} 538 | 539 | /** 540 | * Subtract multiple sets and store the resulting set in a key 541 | * @since 1.0.0 542 | */ 543 | public void sdiffstore(Object... args) {send(RedisCommand.SDIFFSTORE, args);} 544 | 545 | /** 546 | * Remove elements from a list 547 | * @since 1.0.0 548 | */ 549 | public void lrem(Object... args) {send(RedisCommand.LREM, args);} 550 | 551 | /** 552 | * Incrementally iterate the keys space 553 | * @since 2.8.0 554 | */ 555 | public void scan(Object... args) {send(RedisCommand.SCAN, args);} 556 | 557 | /** 558 | * Load the specified Lua script into the script cache. 559 | * @since 2.6.0 560 | */ 561 | public void script_load(Object... args) {send(RedisCommand.SCRIPT_LOAD, args);} 562 | 563 | /** 564 | * Return a serialized version of the value stored at the specified key. 565 | * @since 2.6.0 566 | */ 567 | public void dump(Object... args) {send(RedisCommand.DUMP, args);} 568 | 569 | /** 570 | * Stop listening for messages posted to the given channels 571 | * @since 2.0.0 572 | */ 573 | public void unsubscribe(Object... args) {send(RedisCommand.UNSUBSCRIBE, args);} 574 | 575 | /** 576 | * Intersect multiple sorted sets and store the resulting sorted set in a new key 577 | * @since 2.0.0 578 | */ 579 | public void zinterstore(Object... args) {send(RedisCommand.ZINTERSTORE, args);} 580 | 581 | /** 582 | * Return a range of members in a sorted set, by score 583 | * @since 1.0.5 584 | */ 585 | public void zrangebyscore(Object... args) {send(RedisCommand.ZRANGEBYSCORE, args);} 586 | 587 | /** 588 | * Get the values of all the given keys 589 | * @since 1.0.0 590 | */ 591 | public void mget(Object... args) {send(RedisCommand.MGET, args);} 592 | 593 | /** 594 | * Set the expiration for a key as a UNIX timestamp 595 | * @since 1.2.0 596 | */ 597 | public void expireat(Object... args) {send(RedisCommand.EXPIREAT, args);} 598 | 599 | /** 600 | * Remove all members in a sorted set within the given scores 601 | * @since 1.2.0 602 | */ 603 | public void zremrangebyscore(Object... args) {send(RedisCommand.ZREMRANGEBYSCORE, args);} 604 | 605 | /** 606 | * Determine the index of a member in a sorted set 607 | * @since 2.0.0 608 | */ 609 | public void zrank(Object... args) {send(RedisCommand.ZRANK, args);} 610 | 611 | /** 612 | * Determine if a key exists 613 | * @since 1.0.0 614 | */ 615 | public void exists(Object... args) {send(RedisCommand.EXISTS, args);} 616 | 617 | /** 618 | * Return a range of members in a sorted set, by index 619 | * @since 1.2.0 620 | */ 621 | public void zrange(Object... args) {send(RedisCommand.ZRANGE, args);} 622 | 623 | /** 624 | * Get a substring of the string stored at a key 625 | * @since 2.4.0 626 | */ 627 | public void getrange(Object... args) {send(RedisCommand.GETRANGE, args);} 628 | 629 | /** 630 | * Set the value and expiration of a key 631 | * @since 2.0.0 632 | */ 633 | public void setex(Object... args) {send(RedisCommand.SETEX, args);} 634 | 635 | /** 636 | * Get the number of members in a sorted set 637 | * @since 1.2.0 638 | */ 639 | public void zcard(Object... args) {send(RedisCommand.ZCARD, args);} 640 | 641 | /** 642 | * Reset the stats returned by INFO 643 | * @since 2.0.0 644 | */ 645 | public void config_resetstat(Object... args) {send(RedisCommand.CONFIG_RESETSTAT, args);} 646 | 647 | /** 648 | * Return a range of members in a sorted set, by index, with scores ordered from high to low 649 | * @since 1.2.0 650 | */ 651 | public void zrevrange(Object... args) {send(RedisCommand.ZREVRANGE, args);} 652 | 653 | /** 654 | * Remove and get the first element in a list, or block until one is available 655 | * @since 2.0.0 656 | */ 657 | public void blpop(Object... args) {send(RedisCommand.BLPOP, args);} 658 | 659 | /** 660 | * Add one or more members to a sorted set, or update its score if it already exists 661 | * @since 1.2.0 662 | */ 663 | public void zadd(Object... args) {send(RedisCommand.ZADD, args);} 664 | 665 | /** 666 | * Subtract multiple sets 667 | * @since 1.0.0 668 | */ 669 | public void sdiff(Object... args) {send(RedisCommand.SDIFF, args);} 670 | 671 | /** 672 | * Increment the float value of a hash field by the given amount 673 | * @since 2.6.0 674 | */ 675 | public void hincrbyfloat(Object... args) {send(RedisCommand.HINCRBYFLOAT, args);} 676 | 677 | /** 678 | * Determine if a hash field exists 679 | * @since 2.0.0 680 | */ 681 | public void hexists(Object... args) {send(RedisCommand.HEXISTS, args);} 682 | 683 | /** 684 | * Asynchronously rewrite the append-only file 685 | * @since 1.0.0 686 | */ 687 | public void bgrewriteaof(Object... args) {send(RedisCommand.BGREWRITEAOF, args);} 688 | 689 | /** 690 | * Internal command used for replication 691 | * @since 1.0.0 692 | */ 693 | public void sync(Object... args) {send(RedisCommand.SYNC, args);} 694 | 695 | /** 696 | * Count the number of members in a sorted set between a given lexicographical range 697 | * @since 2.8.9 698 | */ 699 | public void zlexcount(Object... args) {send(RedisCommand.ZLEXCOUNT, args);} 700 | 701 | /** 702 | * Set the string value of a key and return its old value 703 | * @since 1.0.0 704 | */ 705 | public void getset(Object... args) {send(RedisCommand.GETSET, args);} 706 | 707 | /** 708 | * Remove all keys from all databases 709 | * @since 1.0.0 710 | */ 711 | public void flushall(Object... args) {send(RedisCommand.FLUSHALL, args);} 712 | 713 | /** 714 | * Rename a key, only if the new key does not exist 715 | * @since 1.0.0 716 | */ 717 | public void renamenx(Object... args) {send(RedisCommand.RENAMENX, args);} 718 | 719 | /** 720 | * Add multiple sets and store the resulting set in a key 721 | * @since 1.0.0 722 | */ 723 | public void sunionstore(Object... args) {send(RedisCommand.SUNIONSTORE, args);} 724 | 725 | /** 726 | * Incrementally iterate hash fields and associated values 727 | * @since 2.8.0 728 | */ 729 | public void hscan(Object... args) {send(RedisCommand.HSCAN, args);} 730 | 731 | /** 732 | * Sort the elements in a list, set or sorted set 733 | * @since 1.0.0 734 | */ 735 | public void sort(Object... args) {send(RedisCommand.SORT, args);} 736 | 737 | /** 738 | * Get the score associated with the given member in a sorted set 739 | * @since 1.2.0 740 | */ 741 | public void zscore(Object... args) {send(RedisCommand.ZSCORE, args);} 742 | 743 | /** 744 | * Set the string value of a key 745 | * @since 1.0.0 746 | */ 747 | public void set(Object... args) {send(RedisCommand.SET, args);} 748 | 749 | /** 750 | * Synchronously save the dataset to disk 751 | * @since 1.0.0 752 | */ 753 | public void save(Object... args) {send(RedisCommand.SAVE, args);} 754 | 755 | /** 756 | * Execute all commands issued after MULTI 757 | * @since 1.2.0 758 | */ 759 | public void exec(Object... args) {send(RedisCommand.EXEC, args);} 760 | 761 | /** 762 | * Increment the integer value of a hash field by the given number 763 | * @since 2.0.0 764 | */ 765 | public void hincrby(Object... args) {send(RedisCommand.HINCRBY, args);} 766 | 767 | /** 768 | * Get all the fields in a hash 769 | * @since 2.0.0 770 | */ 771 | public void hkeys(Object... args) {send(RedisCommand.HKEYS, args);} 772 | 773 | /** 774 | * Get one or multiple random members from a set 775 | * @since 1.0.0 776 | */ 777 | public void srandmember(Object... args) {send(RedisCommand.SRANDMEMBER, args);} 778 | 779 | /** 780 | * Incrementally iterate Set elements 781 | * @since 2.8.0 782 | */ 783 | public void sscan(Object... args) {send(RedisCommand.SSCAN, args);} 784 | 785 | /** 786 | * Get an element from a list by its index 787 | * @since 1.0.0 788 | */ 789 | public void lindex(Object... args) {send(RedisCommand.LINDEX, args);} 790 | 791 | /** 792 | * Increment the integer value of a key by the given amount 793 | * @since 1.0.0 794 | */ 795 | public void incrby(Object... args) {send(RedisCommand.INCRBY, args);} 796 | 797 | /** 798 | * Get information and statistics about the server 799 | * @since 1.0.0 800 | */ 801 | public void info(Object... args) {send(RedisCommand.INFO, args);} 802 | 803 | /** 804 | * Remove all members in a sorted set within the given indexes 805 | * @since 2.0.0 806 | */ 807 | public void zremrangebyrank(Object... args) {send(RedisCommand.ZREMRANGEBYRANK, args);} 808 | 809 | /** 810 | * Count the members in a sorted set with scores within the given values 811 | * @since 2.0.0 812 | */ 813 | public void zcount(Object... args) {send(RedisCommand.ZCOUNT, args);} 814 | 815 | /** 816 | * Overwrite part of a string at key starting at the specified offset 817 | * @since 2.2.0 818 | */ 819 | public void setrange(Object... args) {send(RedisCommand.SETRANGE, args);} 820 | 821 | /** 822 | * Remove and get the first element in a list 823 | * @since 1.0.0 824 | */ 825 | public void lpop(Object... args) {send(RedisCommand.LPOP, args);} 826 | 827 | /** 828 | * Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s). 829 | * @since 2.8.9 830 | */ 831 | public void pfcount(Object... args) {send(RedisCommand.PFCOUNT, args);} 832 | 833 | /** 834 | * Listen for messages published to channels matching the given patterns 835 | * @since 2.0.0 836 | */ 837 | public void psubscribe(Object... args) {send(RedisCommand.PSUBSCRIBE, args);} 838 | 839 | /** 840 | * Echo the given string 841 | * @since 1.0.0 842 | */ 843 | public void echo(Object... args) {send(RedisCommand.ECHO, args);} 844 | 845 | /** 846 | * Asynchronously save the dataset to disk 847 | * @since 1.0.0 848 | */ 849 | public void bgsave(Object... args) {send(RedisCommand.BGSAVE, args);} 850 | 851 | /** 852 | * Execute a Lua script server side 853 | * @since 2.6.0 854 | */ 855 | public void evalsha(Object... args) {send(RedisCommand.EVALSHA, args);} 856 | 857 | /** 858 | * Prepend one or multiple values to a list 859 | * @since 1.0.0 860 | */ 861 | public void lpush(Object... args) {send(RedisCommand.LPUSH, args);} 862 | 863 | /** 864 | * Remove the expiration from a key 865 | * @since 2.2.0 866 | */ 867 | public void persist(Object... args) {send(RedisCommand.PERSIST, args);} 868 | 869 | /** 870 | * Set a key's time to live in milliseconds 871 | * @since 2.6.0 872 | */ 873 | public void pexpire(Object... args) {send(RedisCommand.PEXPIRE, args);} 874 | 875 | /** 876 | * Stop processing commands from clients for some time 877 | * @since 2.9.50 878 | */ 879 | public void client_pause(Object... args) {send(RedisCommand.CLIENT_PAUSE, args);} 880 | 881 | /** 882 | * Remove and get the last element in a list 883 | * @since 1.0.0 884 | */ 885 | public void rpop(Object... args) {send(RedisCommand.RPOP, args);} 886 | 887 | /** 888 | * Move a key to another database 889 | * @since 1.0.0 890 | */ 891 | public void move(Object... args) {send(RedisCommand.MOVE, args);} 892 | 893 | /** 894 | * Prepend a value to a list, only if the list exists 895 | * @since 2.2.0 896 | */ 897 | public void lpushx(Object... args) {send(RedisCommand.LPUSHX, args);} 898 | 899 | /** 900 | * Decrement the integer value of a key by one 901 | * @since 1.0.0 902 | */ 903 | public void decr(Object... args) {send(RedisCommand.DECR, args);} 904 | 905 | /** 906 | * Get all the values in a hash 907 | * @since 2.0.0 908 | */ 909 | public void hvals(Object... args) {send(RedisCommand.HVALS, args);} 910 | 911 | /** 912 | * Set a configuration parameter to the given value 913 | * @since 2.0.0 914 | */ 915 | public void config_set(Object... args) {send(RedisCommand.CONFIG_SET, args);} 916 | 917 | /** 918 | * Find all keys matching the given pattern 919 | * @since 1.0.0 920 | */ 921 | public void keys(Object... args) {send(RedisCommand.KEYS, args);} 922 | 923 | /** 924 | * Set the value of a hash field, only if the field does not exist 925 | * @since 2.0.0 926 | */ 927 | public void hsetnx(Object... args) {send(RedisCommand.HSETNX, args);} 928 | 929 | /** 930 | * Returns the bit value at offset in the string value stored at key 931 | * @since 2.2.0 932 | */ 933 | public void getbit(Object... args) {send(RedisCommand.GETBIT, args);} 934 | 935 | /** 936 | * Get the list of client connections 937 | * @since 2.4.0 938 | */ 939 | public void client_list(Object... args) {send(RedisCommand.CLIENT_LIST, args);} 940 | 941 | /** 942 | * Set the current connection name 943 | * @since 2.6.9 944 | */ 945 | public void client_setname(Object... args) {send(RedisCommand.CLIENT_SETNAME, args);} 946 | 947 | /** 948 | * Post a message to a channel 949 | * @since 2.0.0 950 | */ 951 | public void publish(Object... args) {send(RedisCommand.PUBLISH, args);} 952 | 953 | /** 954 | * Remove all members in a sorted set between the given lexicographical range 955 | * @since 2.8.9 956 | */ 957 | public void zremrangebylex(Object... args) {send(RedisCommand.ZREMRANGEBYLEX, args);} 958 | 959 | /** 960 | * Remove all the scripts from the script cache. 961 | * @since 2.6.0 962 | */ 963 | public void script_flush(Object... args) {send(RedisCommand.SCRIPT_FLUSH, args);} 964 | 965 | /** 966 | * Get debugging information about a key 967 | * @since 1.0.0 968 | */ 969 | public void debug_object(Object... args) {send(RedisCommand.DEBUG_OBJECT, args);} 970 | 971 | 972 | } --------------------------------------------------------------------------------