Skip to content

DATAREDIS-73 - Add support for spring managed transactions. #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dependencies {
compile "org.springframework:spring-context:$springVersion"
compile "org.springframework:spring-tx:$springVersion"
compile("org.springframework:spring-oxm:$springVersion", optional)
compile "org.springframework:spring-aop:$springVersion"

// Redis Drivers
compile("redis.clients:jedis:$jedisVersion", optional)
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jredisVersion=06052013
jedisVersion=2.4.1
springVersion=3.2.8.RELEASE
log4jVersion=1.2.17
version=1.3.0.BUILD-SNAPSHOT
version=1.3.0.DATAREDIS-73-SNAPSHOT
srpVersion=0.7
jacksonVersion=1.8.8
fasterXmlJacksonVersion=2.2.0
Expand Down
365 changes: 365 additions & 0 deletions src/main/java/org/springframework/data/redis/core/RedisCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,365 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.jredis.Redis;
import org.springframework.util.StringUtils;

/**
* @author Christoph Strobl
* @author Thomas Darimont
* @since 1.3
* @see Redis command list:
* https://github.com/antirez/redis/blob/93e7a130fc9594e41ccfc996b5eca7626ae5356a/src/redis.c#L119
*/
enum RedisCommand {
// -- A
APPEND("rw", 2, 2), //
AUTH("rw", 1, 1), //
// -- B
BGREWRITEAOF("r", 0, 0, "bgwriteaof"), //
BGSAVE("r", 0, 0), //
BITCOUNT("r", 1, 3), //
BITOP("rw", 3), //
BITPOS("r", 2, 4), //
BLPOP("rw", 2), //
BRPOP("rw", 2), //
BRPOPLPUSH("rw", 3), //
// -- C
CLIENT_KILL("rw", 1, 1), //
CLIENT_LIST("r", 0, 0), //
CLIENT_GETNAME("r", 0, 0), //
CLIENT_PAUSE("rw", 1, 1), //
CLIENT_SETNAME("w", 1, 1), //
CONFIG_GET("r", 1, 1, "getconfig"), //
CONFIG_REWRITE("rw", 0, 0), //
CONFIG_SET("w", 2, 2, "setconfig"), //
CONFIG_RESETSTAT("w", 0, 0, "resetconfigstats"), //
// -- D
DBSIZE("r", 0, 0), //
DECR("w", 1, 1), //
DECRBY("w", 2, 2), //
DEL("rw", 1), //
DISCARD("rw", 0, 0), //
DUMP("r", 1, 1), //
// -- E
ECHO("r", 1, 1), //
EVAL("rw", 2), //
EVALSHA("rw", 2), //
EXEC("rw", 0, 0), //
EXISTS("r", 1, 1), //
EXPIRE("rw", 2, 2), //
EXPIREAT("rw", 2, 2), //
// -- F
FLUSHALL("w", 0, 0), //
FLUSHDB("w", 0, 0), //
// -- G
GET("r", 1, 1), //
GETBIT("r", 2, 2), //
GETRANGE("r", 3, 3), //
GETSET("rw", 2, 2), //
// -- H
HDEL("rw", 2), //
HEXISTS("r", 2, 2), //
HGET("r", 2, 2), //
HGETALL("r", 1, 1), //
HINCRBY("rw", 3, 3), //
HINCBYFLOAT("rw", 3, 3), //
HKEYS("r", 1), //
HLEN("r", 1), //
HMGET("r", 2), //
HMSET("w", 3), //
HSET("w", 3, 3), //
HSETNX("w", 3, 3), //
HVALS("r", 1, 1), //
// -- I
INCR("rw", 1), //
INCRBYFLOAT("rw", 2, 2), //
INFO("r", 0), //
// -- K
KEYS("r", 1), //
// -- L
LASTSAVE("r", 0), //
LINDEX("r", 2, 2), //
LINSERT("rw", 4, 4), //
LLEN("r", 1, 1), //
LPOP("rw", 1, 1), //
LPUSH("rw", 2), //
LPUSHX("rw", 2), //
LRANGE("r", 3, 3), //
LREM("rw", 3, 3), //
LSET("w", 3, 3), //
LTRIM("w", 3, 3), //
// -- M
MGET("r", 1), //
MIGRATE("rw", 0), //
MONITOR("rw", 0, 0), //
MOVE("rw", 2, 2), //
MSET("w", 2), //
MSETNX("w", 2), //
MULTI("rw", 0, 0), //
// -- P
PERSIST("rw", 1, 1), //
PEXPIRE("rw", 2, 2), //
PEXPIREAT("rw", 2, 2), //
PING("r", 0, 0), //
PSETEX("w", 3), //
PSUBSCRIBE("r", 1), //
PTTL("r", 1, 1), //
// -- Q
QUIT("rw", 0, 0), //
// -- R
RANDOMKEY("r", 0, 0), //
RANAME("w", 2, 2), //
RENAMENX("w", 2, 2), //
RESTORE("w", 3, 3), //
RPOP("rw", 1, 1), //
RPOPLPUSH("rw", 2, 2), //
RPUSH("rw", 2), //
RPUSHX("rw", 2, 2), //
// -- S
SADD("rw", 2), //
SAVE("rw", 0, 0), //
SCARD("r", 1, 1), //
SCRIPT_EXISTS("r", 1), //
SCRIPT_FLUSH("rw", 0, 0), //
SCRIPT_KILL("rw", 0, 0), //
SCRIPT_LOAD("rw", 1, 1), //
SDIFF("r", 1), //
SDIFFSTORE("rw", 2), //
SELECT("rw", 0, 0), //
SET("w", 2), //
SETBIT("rw", 3, 3), //
SETEX("w", 3, 3), //
SETNX("w", 2, 2), //
SETRANGE("rw", 3, 3), //
SHUTDOWN("rw", 0), //
SINTER("r", 1), //
SINTERSTORE("rw", 2), //
SISMEMBER("r", 2), //
SLAVEOF("w", 2), //
SLOWLOG("rw", 1), //
SMEMBERS("r", 1, 1), //
SMOVE("rw", 3, 3), //
SORT("rw", 1), //
SPOP("rw", 1, 1), //
SRANDMEMBER("r", 1, 1), //
SREM("rw", 2), //
STRLEN("r", 1, 1), //
SUBSCRIBE("rw", 1), //
SUNION("r", 1), //
SUNIONSTORE("rw ", 2), //
SYNC("rw", 0, 0), //
// -- T
TIME("r", 0, 0), //
TTL("r", 1, 1), //
TYPE("r", 1, 1), //
// -- U
UNSUBSCRIBE("rw", 0), //
UNWATCH("rw", 0, 0), //
// -- W
WATCH("rw", 1), //
// -- Z
ZADD("rw", 3), //
ZCARD("r", 1), //
ZCOUNT("r", 3, 3), //
ZINCRBY("rw", 3), //
ZINTERSTORE("rw", 3), //
ZRANGE("r", 3), //
ZRANGEBYSCORE("r", 3), //
ZRANK("r", 2, 2), //
ZREM("rw", 2), //
ZREMRANGEBYRANK("rw", 3, 3), //
ZREMRANGEBYSCORE("rm", 3, 3), //
ZREVRANGE("r", 3), //
ZREVRANGEBYSCORE("r", 3), //
ZREVRANK("r", 2, 2), //
ZSCORE("r", 2, 2), //
ZUNIONSTORE("rw", 3), //
SCAN("r", 1), //
SSCAN("r", 2), //
HSCAN("r", 2), //
ZSCAN("r", 2), //
// -- UNKNOWN / DEFAULT
UNKNOWN("rw", -1);

private boolean read = true;
private boolean write = true;
private Set<String> alias = new HashSet<String>(1);

private int minArgs = -1;
private int maxArgs = -1;

private final static Map<String, RedisCommand> commandLookup;

static {
commandLookup = buildCommandLookupTable();
}

private static Map<String, RedisCommand> buildCommandLookupTable() {

RedisCommand[] cmds = RedisCommand.values();
Map<String, RedisCommand> map = new HashMap<String, RedisCommand>(cmds.length, 1.0F);

for (RedisCommand cmd : cmds) {

map.put(cmd.name().toLowerCase(), cmd);

for (String alias : cmd.alias) {
map.put(alias, cmd);
}
}

return Collections.unmodifiableMap(map);
}

private RedisCommand(String mode, int minArgs) {
this(mode, minArgs, -1);
}

private RedisCommand(String mode, int minArgs, int maxArgs) {

if (StringUtils.hasText(mode)) {
this.read = mode.toLowerCase().indexOf('r') > -1;
this.write = mode.toLowerCase().indexOf('w') > -1;
}

this.minArgs = minArgs;
this.maxArgs = maxArgs;
}

/**
* Creates a new {@link RedisCommand}.
*
* @param mode
* @param minArgs
* @param maxArgs
* @param alias
*/
private RedisCommand(String mode, int minArgs, int maxArgs, String... alias) {

this(mode, minArgs, maxArgs);

if (alias != null && alias.length > 0) {
this.alias.addAll(Arrays.asList(alias));
}
}

/**
* @return {@literal true} if the command requires arguments
*/
public boolean requiresArguments() {
return minArgs >= 0;
}

/**
* @return {@literal true} if an exact number of arguments is expected
*/
public boolean requiresExactNumberOfArguments() {
return maxArgs >= 0;
}

/**
* @return {@literal true} if the command triggers a read operation
*/
public boolean isRead() {
return read;
}

/**
* @return {@literal true} if the command triggers a write operation
*/
public boolean isWrite() {
return write;
}

/**
* @return {@literal true} if values are read but not written
*/
public boolean isReadonly() {
return read && !write;
}

/**
* {@link String#equalsIgnoreCase(String)} compare the given string representation of {@literal command} against the
* {@link #toString()} representation of the command as well as its given {@link #alias}.
*
* @param command
* @return true if positive match.
*/
public boolean isRepresentedBy(String command) {

if (!StringUtils.hasText(command)) {
return false;
}

if (toString().equalsIgnoreCase(command)) {
return true;
}

return alias.contains(command.toLowerCase());
}

/**
* Validates given argument count against expected ones.
*
* @param nrArguments
* @throws {@link IllegalArgumentException} in case argument count does not match expected.
*/
public void validateArgumentCount(int nrArguments) {

if (requiresArguments()) {
if (requiresExactNumberOfArguments()) {
if (nrArguments != maxArgs) {
throw new IllegalArgumentException(String.format("%s command requires %s arguments.", this.name(),
this.maxArgs));
}
}
if (nrArguments < minArgs) {
throw new IllegalArgumentException(String.format("%s command requires at least %s arguments.", this.name(),
this.minArgs));
}
}
}

/**
* Returns the command represented by the given {@code key}. Returns {@link #UNKNOWN} if no matching command could be
* found.
*
* @param key
* @return
*/
public static RedisCommand failsafeCommandLookup(String key) {

if (!StringUtils.hasText(key)) {
return RedisCommand.UNKNOWN;
}

RedisCommand cmd = commandLookup.get(key.toLowerCase());
if (cmd != null) {
return cmd;
}

return RedisCommand.UNKNOWN;
}
}
Loading