Skip to content

Commit 6f9fb61

Browse files
denglimingsazzad16
andauthored
Add support for clientUnblock command (#2424)
* Add support for clientUnblock command * Implement Rawable interface. * fix * Add javadoc Co-authored-by: M Sazzadul Hoque <[email protected]>
1 parent 17b4550 commit 6f9fb61

File tree

9 files changed

+92
-1
lines changed

9 files changed

+92
-1
lines changed

src/main/java/redis/clients/jedis/BinaryClient.java

+9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import javax.net.ssl.SSLSocketFactory;
2828

2929
import redis.clients.jedis.Protocol.Keyword;
30+
import redis.clients.jedis.args.UnblockType;
3031
import redis.clients.jedis.params.*;
3132
import redis.clients.jedis.util.SafeEncoder;
3233

@@ -1232,6 +1233,14 @@ public void clientId() {
12321233
sendCommand(CLIENT, Keyword.ID.getRaw());
12331234
}
12341235

1236+
public void clientUnblock(final long clientId, final UnblockType unblockType) {
1237+
if (unblockType == null) {
1238+
sendCommand(CLIENT, Keyword.UNBLOCK.getRaw(), toByteArray(clientId));
1239+
} else {
1240+
sendCommand(CLIENT, Keyword.UNBLOCK.getRaw(), toByteArray(clientId), unblockType.getRaw());
1241+
}
1242+
}
1243+
12351244
public void time() {
12361245
sendCommand(TIME);
12371246
}

src/main/java/redis/clients/jedis/BinaryJedis.java

+15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.net.ssl.SSLParameters;
2121
import javax.net.ssl.SSLSocketFactory;
2222

23+
import redis.clients.jedis.args.UnblockType;
2324
import redis.clients.jedis.commands.AdvancedBinaryJedisCommands;
2425
import redis.clients.jedis.commands.BasicCommands;
2526
import redis.clients.jedis.commands.BinaryJedisCommands;
@@ -4076,6 +4077,20 @@ public Long clientId() {
40764077
return client.getIntegerReply();
40774078
}
40784079

4080+
/**
4081+
* Unblock a client blocked in a blocking command from a different connection.
4082+
* @param clientId
4083+
* @param unblockType could be {@code null} by default the client is unblocked as if the timeout
4084+
* of the command was reached
4085+
* @return
4086+
*/
4087+
@Override
4088+
public Long clientUnblock(final long clientId, final UnblockType unblockType) {
4089+
checkIsInMultiOrPipeline();
4090+
client.clientUnblock(clientId, unblockType);
4091+
return client.getIntegerReply();
4092+
}
4093+
40794094
public String clientPause(final long timeout) {
40804095
checkIsInMultiOrPipeline();
40814096
client.clientPause(timeout);

src/main/java/redis/clients/jedis/Jedis.java

+15
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import javax.net.ssl.SSLParameters;
1414
import javax.net.ssl.SSLSocketFactory;
1515

16+
import redis.clients.jedis.args.UnblockType;
1617
import redis.clients.jedis.commands.AdvancedJedisCommands;
1718
import redis.clients.jedis.commands.BasicCommands;
1819
import redis.clients.jedis.commands.ClusterCommands;
@@ -3428,6 +3429,20 @@ public Long clientId() {
34283429
return client.getIntegerReply();
34293430
}
34303431

3432+
/**
3433+
* Unblock a client blocked in a blocking command from a different connection.
3434+
* @param clientId
3435+
* @param unblockType could be {@code null} by default the client is unblocked as if the timeout
3436+
* of the command was reached
3437+
* @return
3438+
*/
3439+
@Override
3440+
public Long clientUnblock(final long clientId, final UnblockType unblockType) {
3441+
checkIsInMultiOrPipeline();
3442+
client.clientUnblock(clientId, unblockType);
3443+
return client.getIntegerReply();
3444+
}
3445+
34313446
@Override
34323447
public String migrate(final String host, final int port, final String key,
34333448
final int destinationDb, final int timeout) {

src/main/java/redis/clients/jedis/Protocol.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public static enum Keyword implements Rawable {
283283
GETNAME, SETNAME, LIST, MATCH, COUNT, PING, PONG, UNLOAD, REPLACE, KEYS, PAUSE, DOCTOR, BLOCK,
284284
NOACK, STREAMS, KEY, CREATE, MKSTREAM, SETID, DESTROY, DELCONSUMER, MAXLEN, GROUP, ID, IDLE,
285285
TIME, RETRYCOUNT, FORCE, USAGE, SAMPLES, STREAM, GROUPS, CONSUMERS, HELP, FREQ, SETUSER,
286-
GETUSER, DELUSER, WHOAMI, CAT, GENPASS, USERS, LOG, INCR, SAVE, JUSTID, WITHVALUES;
286+
GETUSER, DELUSER, WHOAMI, CAT, GENPASS, USERS, LOG, INCR, SAVE, JUSTID, WITHVALUES, UNBLOCK;
287287

288288
/**
289289
* @deprecated This will be private in future. Use {@link #getRaw()}.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package redis.clients.jedis.args;
2+
3+
import redis.clients.jedis.util.SafeEncoder;
4+
5+
/**
6+
* Unblock type for {@code CLIENT UNBLOCK} command.
7+
*/
8+
public enum UnblockType implements Rawable {
9+
TIMEOUT, ERROR;
10+
11+
private final byte[] raw;
12+
13+
UnblockType() {
14+
raw = SafeEncoder.encode(this.name());
15+
}
16+
17+
@Override
18+
public byte[] getRaw() {
19+
return raw;
20+
}
21+
}

src/main/java/redis/clients/jedis/commands/AdvancedBinaryJedisCommands.java

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.List;
44

55
import redis.clients.jedis.AccessControlUser;
6+
import redis.clients.jedis.args.UnblockType;
67
import redis.clients.jedis.params.MigrateParams;
78
import redis.clients.jedis.params.ClientKillParams;
89

@@ -41,6 +42,8 @@ String migrate(String host, int port, int destinationDB, int timeout, MigratePar
4142

4243
Long clientKill(ClientKillParams params);
4344

45+
Long clientUnblock(long clientId, UnblockType unblockType);
46+
4447
byte[] clientGetnameBinary();
4548

4649
byte[] clientListBinary();

src/main/java/redis/clients/jedis/commands/AdvancedJedisCommands.java

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import redis.clients.jedis.AccessControlLogEntry;
66
import redis.clients.jedis.AccessControlUser;
7+
import redis.clients.jedis.args.UnblockType;
78
import redis.clients.jedis.params.MigrateParams;
89
import redis.clients.jedis.params.ClientKillParams;
910
import redis.clients.jedis.util.Slowlog;
@@ -50,6 +51,8 @@ String migrate(String host, int port, int destinationDB, int timeout, MigratePar
5051

5152
Long clientId();
5253

54+
Long clientUnblock(long clientId, UnblockType unblockType);
55+
5356
String memoryDoctor();
5457

5558
Long memoryUsage(String key);

src/main/java/redis/clients/jedis/commands/Commands.java

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import redis.clients.jedis.ListPosition;
99
import redis.clients.jedis.ScanParams;
1010
import redis.clients.jedis.SortingParams;
11+
import redis.clients.jedis.args.UnblockType;
1112
import redis.clients.jedis.ZParams;
1213
import redis.clients.jedis.params.GetExParams;
1314
import redis.clients.jedis.params.MigrateParams;
@@ -430,6 +431,8 @@ default void restoreReplace(String key, int ttl, byte[] serializedValue) {
430431

431432
void clientId();
432433

434+
void clientUnblock(long clientId, UnblockType unblockType);
435+
433436
void memoryDoctor();
434437

435438
void xadd(String key, StreamEntryID id, Map<String, String> hash, long maxLen, boolean approximateLength);

src/test/java/redis/clients/jedis/tests/commands/ClientCommandsTest.java

+22
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
import static redis.clients.jedis.params.ClientKillParams.Type;
88
import static redis.clients.jedis.params.ClientKillParams.SkipMe;
99

10+
import java.util.concurrent.ExecutionException;
11+
import java.util.concurrent.Executors;
12+
import java.util.concurrent.Future;
13+
import java.util.concurrent.TimeUnit;
14+
import java.util.concurrent.TimeoutException;
1015
import java.util.regex.Matcher;
1116
import java.util.regex.Pattern;
1217

@@ -16,6 +21,7 @@
1621

1722
import redis.clients.jedis.HostAndPort;
1823
import redis.clients.jedis.Jedis;
24+
import redis.clients.jedis.args.UnblockType;
1925
import redis.clients.jedis.exceptions.JedisConnectionException;
2026
import redis.clients.jedis.params.ClientKillParams;
2127

@@ -93,6 +99,22 @@ public void clientIdReconnect() {
9399
assertTrue(clientIdInitial < clientIdAfterReconnect);
94100
}
95101

102+
@Test
103+
public void clientUnblock() throws InterruptedException, TimeoutException {
104+
long clientId = client.clientId();
105+
assertEquals(0, jedis.clientUnblock(clientId, UnblockType.ERROR).longValue());
106+
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> client.brpop(100000, "foo"));
107+
108+
try {
109+
// to make true command already executed
110+
TimeUnit.MILLISECONDS.sleep(500);
111+
assertEquals(1, jedis.clientUnblock(clientId, UnblockType.ERROR).longValue());
112+
future.get(1, TimeUnit.SECONDS);
113+
} catch (ExecutionException e) {
114+
assertEquals("redis.clients.jedis.exceptions.JedisDataException: UNBLOCKED client unblocked via CLIENT UNBLOCK", e.getMessage());
115+
}
116+
}
117+
96118
@Test
97119
public void killIdString() {
98120
String info = findInClientList();

0 commit comments

Comments
 (0)