Skip to content

Commit

Permalink
Support COMMAND commands (#2922)
Browse files Browse the repository at this point in the history
Co-authored-by: M Sazzadul Hoque <[email protected]>
  • Loading branch information
Avital-Fine and sazzad16 authored Mar 9, 2022
1 parent 31513d4 commit 3590438
Show file tree
Hide file tree
Showing 8 changed files with 473 additions and 22 deletions.
54 changes: 54 additions & 0 deletions src/main/java/redis/clients/jedis/BuilderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,15 @@ public String toString() {
}
};

public static final Builder<List<KeyValue<String, List<String>>>> KEYED_STRING_LIST_LIST
= new Builder<List<KeyValue<String, List<String>>>>() {
@Override
public List<KeyValue<String, List<String>>> build(Object data) {
List<Object> list = (List<Object>) data;
return list.stream().map(KEYED_STRING_LIST::build).collect(Collectors.toList());
}
};

public static final Builder<KeyValue<byte[], List<byte[]>>> KEYED_BINARY_LIST
= new Builder<KeyValue<byte[], List<byte[]>>>() {
@Override
Expand Down Expand Up @@ -772,6 +781,51 @@ public String toString() {
}
};

public static final Builder<Map<String, CommandDocument>> COMMAND_DOCS_RESPONSE = new Builder<Map<String, CommandDocument>>() {
@Override
public Map<String, CommandDocument> build(Object data) {
if (data == null) {
return null;
}

List<Object> list = (List<Object>) data;
Map<String, CommandDocument> map = new HashMap<>(list.size());

for (int i = 0; i < list.size();) {
String name = STRING.build(list.get(i++));
CommandDocument doc = CommandDocument.COMMAND_DOCUMENT_BUILDER.build(list.get(i++));
map.put(name, doc);
}

return map;
}
};

public static final Builder<Map<String, CommandInfo>> COMMAND_INFO_RESPONSE = new Builder<Map<String, CommandInfo>>() {
@Override
public Map<String, CommandInfo> build(Object data) {
if (data == null) {
return null;
}

List<Object> rawList = (List<Object>) data;
Map<String, CommandInfo> map = new HashMap<>(rawList.size());

for (Object rawCommandInfo : rawList) {
if (rawCommandInfo == null) {
continue;
}

List<Object> commandInfo = (List<Object>) rawCommandInfo;
String name = STRING.build(commandInfo.get(0));
CommandInfo info = CommandInfo.COMMAND_INFO_BUILDER.build(commandInfo);
map.put(name, info);
}

return map;
}
};

public static final Builder<List<Module>> MODULE_LIST = new Builder<List<Module>>() {
@Override
public List<Module> build(Object data) {
Expand Down
51 changes: 47 additions & 4 deletions src/main/java/redis/clients/jedis/Jedis.java
Original file line number Diff line number Diff line change
Expand Up @@ -8042,6 +8042,49 @@ public long bitop(final BitOP op, final String destKey, final String... srcKeys)
return connection.executeCommand(commandObjects.bitop(op, destKey, srcKeys));
}

public long commandCount() {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, COUNT);
return connection.getIntegerReply();
}

public Map<String, CommandDocument> commandDocs(String... commands) {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, joinParameters(DOCS.name(), commands));
return BuilderFactory.COMMAND_DOCS_RESPONSE.build(connection.getOne());
}

public List<String> commandGetKeys(String... command) {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, joinParameters(GETKEYS.name(), command));
return BuilderFactory.STRING_LIST.build(connection.getOne());
}

public List<KeyValue<String, List<String>>> commandGetKeysAndFlags(String... command) {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, joinParameters(GETKEYSANDFLAGS.name(), command));
return BuilderFactory.KEYED_STRING_LIST_LIST.build(connection.getOne());
}

public Map<String, CommandInfo> commandInfo(String... commands) {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, joinParameters(Keyword.INFO.name(), commands));
return BuilderFactory.COMMAND_INFO_RESPONSE.build(connection.getOne());
}

public List<String> commandList() {
checkIsInMultiOrPipeline();
connection.sendCommand(COMMAND, LIST);
return BuilderFactory.STRING_LIST.build(connection.getOne());
}

public List<String> commandListFilterBy(CommandListFilterByParams filterByParams) {
checkIsInMultiOrPipeline();
CommandArguments args = new CommandArguments(COMMAND).add(LIST).addParams(filterByParams);
connection.sendCommand(args);
return BuilderFactory.STRING_LIST.build(connection.getOne());
}

@Override
public String sentinelMyId() {
connection.sendCommand(SENTINEL, MYID);
Expand Down Expand Up @@ -8993,28 +9036,28 @@ public long geosearchStoreStoreDist(String dest, String src, GeoSearchParam para
@Override
public String moduleLoad(final String path) {
checkIsInMultiOrPipeline();
connection.sendCommand(MODULE, LOAD.name(), path);
connection.sendCommand(Command.MODULE, LOAD.name(), path);
return connection.getStatusCodeReply();
}

@Override
public String moduleLoad(String path, String... args) {
checkIsInMultiOrPipeline();
connection.sendCommand(MODULE, joinParameters(LOAD.name(), path, args));
connection.sendCommand(Command.MODULE, joinParameters(LOAD.name(), path, args));
return connection.getStatusCodeReply();
}

@Override
public String moduleUnload(final String name) {
checkIsInMultiOrPipeline();
connection.sendCommand(MODULE, UNLOAD.name(), name);
connection.sendCommand(Command.MODULE, UNLOAD.name(), name);
return connection.getStatusCodeReply();
}

@Override
public List<Module> moduleList() {
checkIsInMultiOrPipeline();
connection.sendCommand(MODULE, LIST);
connection.sendCommand(Command.MODULE, LIST);
return BuilderFactory.MODULE_LIST.build(connection.getObjectMultiBulkReply());
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/redis/clients/jedis/Protocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public static enum Command implements ProtocolCommand {
XADD, XLEN, XDEL, XTRIM, XRANGE, XREVRANGE, XREAD, XACK, XGROUP, XREADGROUP, XPENDING, XCLAIM,
XAUTOCLAIM, XINFO, BITFIELD_RO, ROLE, FAILOVER, GEOSEARCH, GEOSEARCHSTORE, EVAL_RO, EVALSHA_RO,
LOLWUT, EXPIRETIME, PEXPIRETIME, FUNCTION, FCALL, FCALL_RO, LMPOP, BLMPOP, ZMPOP, BZMPOP,
@Deprecated STRALGO;
COMMAND, @Deprecated STRALGO;

private final byte[] raw;

Expand All @@ -262,8 +262,8 @@ public static enum Keyword implements Rawable {
TIMEOUT, ABORT, NX, XX, EX, PX, EXAT, PXAT, CH, WITHCOORD, WITHDIST, WITHHASH, STOREDIST, COPY,
KEEPTTL, AUTH, AUTH2, INFO, CHANNELS, NUMPAT, NUMSUB, FULL, NOW, VERSION, KEYS, IDX, SCHEDULE,
ANY, FROMMEMBER, FROMLONLAT, BYRADIUS, BYBOX, BYLEX, BYSCORE, REV, MINMATCHLEN, WITHMATCHLEN,
PURGE, STATS, CREATECONSUMER, DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION,
@Deprecated LCS, @Deprecated STRINGS;
PURGE, STATS, CREATECONSUMER, DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION, GETKEYS, GETKEYSANDFLAGS,
DOCS, FILTERBY, MODULE, ACLCAT, PATTERN, @Deprecated LCS, @Deprecated STRINGS;

private final byte[] raw;

Expand Down
61 changes: 61 additions & 0 deletions src/main/java/redis/clients/jedis/commands/CommandCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package redis.clients.jedis.commands;

import redis.clients.jedis.params.CommandListFilterByParams;
import redis.clients.jedis.resps.CommandDocument;
import redis.clients.jedis.resps.CommandInfo;
import redis.clients.jedis.util.KeyValue;

import java.util.List;
import java.util.Map;

public interface CommandCommands {

/**
* The number of total commands in this Redis server
* @return The number of total commands
*/
long commandCount();

/**
* Return documentary information about commands.
* If not specifying commands, the reply includes all the server's commands.
* @param commands specify the names of one or more commands
* @return list of {@link CommandDocument}
*/

Map<String, CommandDocument> commandDocs(String... commands);

/**
* Return list of keys from a full Redis command
* @param command
* @return list of keys
*/
List<String> commandGetKeys(String... command);

/**
* Return list of keys from a full Redis command and their usage flags
* @param command
* @return list of {@link KeyValue}
*/
List<KeyValue<String, List<String>>> commandGetKeysAndFlags(String... command);

/**
* Return details about multiple Redis commands
* @param commands
* @return list of {@link CommandInfo}
*/
Map<String, CommandInfo> commandInfo(String... commands);

/**
* Return a list of the server's command names
* @return commands list
*/
List<String> commandList();

/**
* Return a list of the server's command names filtered by module's name, ACL category or pattern
* @param filterByParams {@link CommandListFilterByParams}
* @return commands list
*/
List<String> commandListFilterBy(CommandListFilterByParams filterByParams);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package redis.clients.jedis.params;

import redis.clients.jedis.CommandArguments;
import redis.clients.jedis.exceptions.JedisDataException;

import static redis.clients.jedis.Protocol.Keyword.FILTERBY;
import static redis.clients.jedis.Protocol.Keyword.MODULE;
import static redis.clients.jedis.Protocol.Keyword.ACLCAT;
import static redis.clients.jedis.Protocol.Keyword.PATTERN;

public class CommandListFilterByParams implements IParams {
private String moduleName;
private String category;
private String pattern;

public static CommandListFilterByParams commandListFilterByParams() {
return new CommandListFilterByParams();
}

public CommandListFilterByParams filterByModule(String moduleName) {
this.moduleName = moduleName;
return this;
}

public CommandListFilterByParams filterByAclCat(String category) {
this.category = category;
return this;
}

public CommandListFilterByParams filterByPattern(String pattern) {
this.pattern = pattern;
return this;
}

@Override
public void addParams(CommandArguments args) {
args.add(FILTERBY);

if (moduleName != null && category == null && pattern == null) {
args.add(MODULE);
args.add(moduleName);
} else if (moduleName == null && category != null && pattern == null) {
args.add(ACLCAT);
args.add(category);
} else if (moduleName == null && category == null && pattern != null) {
args.add(PATTERN);
args.add(pattern);
} else {
throw new JedisDataException("Must choose exactly one filter");
}
}
}
64 changes: 64 additions & 0 deletions src/main/java/redis/clients/jedis/resps/CommandDocument.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package redis.clients.jedis.resps;

import redis.clients.jedis.Builder;

import static redis.clients.jedis.BuilderFactory.STRING;

import java.util.ArrayList;
import java.util.List;

public class CommandDocument {
private final String summary;
private final String since;
private final String group;
private final String complexity;
private final List<String> history;

public CommandDocument(String summary, String since, String group, String complexity, List<String> history) {
this.summary = summary;
this.since = since;
this.group = group;
this.complexity = complexity;
this.history = history;
}

public String getSummary() {
return summary;
}

public String getSince() {
return since;
}

public String getGroup() {
return group;
}

public String getComplexity() {
return complexity;
}

public List<String> getHistory() {
return history;
}

public static final Builder<CommandDocument> COMMAND_DOCUMENT_BUILDER = new Builder<CommandDocument>() {
@Override
public CommandDocument build(Object data) {
List<Object> commandData = (List<Object>) data;
String summary = STRING.build(commandData.get(1));
String since = STRING.build(commandData.get(3));
String group = STRING.build(commandData.get(5));
String complexity = STRING.build(commandData.get(7));
List<String> history = null;
if (STRING.build(commandData.get(8)).equals("history")) {
List<List<Object>> rawHistory = (List<List<Object>>) commandData.get(9);
history = new ArrayList<>(rawHistory.size());
for (List<Object> timePoint : rawHistory) {
history.add(STRING.build(timePoint.get(0)) + ": " + STRING.build(timePoint.get(1)));
}
}
return new CommandDocument(summary, since, group, complexity, history);
}
};
}
Loading

0 comments on commit 3590438

Please sign in to comment.