37
37
import io .lettuce .core .protocol .Command ;
38
38
import io .lettuce .core .protocol .CommandArgs ;
39
39
import io .lettuce .core .protocol .CommandType ;
40
+ import io .lettuce .core .protocol .ProtocolKeyword ;
40
41
import io .lettuce .core .pubsub .StatefulRedisPubSubConnection ;
41
42
import io .lettuce .core .sentinel .api .StatefulRedisSentinelConnection ;
42
43
43
44
import java .lang .reflect .Constructor ;
45
+ import java .nio .charset .StandardCharsets ;
44
46
import java .util .ArrayList ;
45
47
import java .util .Collections ;
46
48
import java .util .HashMap ;
@@ -404,7 +406,7 @@ public Object execute(String command, @Nullable CommandOutput commandOutputTypeH
404
406
try {
405
407
406
408
String name = command .trim ().toUpperCase ();
407
- CommandType commandType = CommandType . valueOf (name );
409
+ ProtocolKeyword commandType = getCommandType (name );
408
410
409
411
validateCommandIfRunningInTransactionMode (commandType , args );
410
412
@@ -1045,14 +1047,14 @@ io.lettuce.core.ScanCursor getScanCursor(long cursorId) {
1045
1047
return io .lettuce .core .ScanCursor .of (Long .toString (cursorId ));
1046
1048
}
1047
1049
1048
- private void validateCommandIfRunningInTransactionMode (CommandType cmd , byte []... args ) {
1050
+ private void validateCommandIfRunningInTransactionMode (ProtocolKeyword cmd , byte []... args ) {
1049
1051
1050
1052
if (this .isQueueing ()) {
1051
1053
validateCommand (cmd , args );
1052
1054
}
1053
1055
}
1054
1056
1055
- private void validateCommand (CommandType cmd , @ Nullable byte []... args ) {
1057
+ private void validateCommand (ProtocolKeyword cmd , @ Nullable byte []... args ) {
1056
1058
1057
1059
RedisCommand redisCommand = RedisCommand .failsafeCommandLookup (cmd .name ());
1058
1060
if (!RedisCommand .UNKNOWN .equals (redisCommand ) && redisCommand .requiresArguments ()) {
@@ -1105,6 +1107,15 @@ LettuceConnectionProvider getConnectionProvider() {
1105
1107
return connectionProvider ;
1106
1108
}
1107
1109
1110
+ private static ProtocolKeyword getCommandType (String name ) {
1111
+
1112
+ try {
1113
+ return CommandType .valueOf (name );
1114
+ } catch (IllegalArgumentException e ) {
1115
+ return new CustomCommandType (name );
1116
+ }
1117
+ }
1118
+
1108
1119
/**
1109
1120
* {@link TypeHints} provide {@link CommandOutput} information for a given {@link CommandType}.
1110
1121
*
@@ -1113,7 +1124,7 @@ LettuceConnectionProvider getConnectionProvider() {
1113
1124
static class TypeHints {
1114
1125
1115
1126
@ SuppressWarnings ("rawtypes" ) //
1116
- private static final Map <CommandType , Class <? extends CommandOutput >> COMMAND_OUTPUT_TYPE_MAPPING = new HashMap <>();
1127
+ private static final Map <ProtocolKeyword , Class <? extends CommandOutput >> COMMAND_OUTPUT_TYPE_MAPPING = new HashMap <>();
1117
1128
1118
1129
@ SuppressWarnings ("rawtypes" ) //
1119
1130
private static final Map <Class <?>, Constructor <CommandOutput >> CONSTRUCTORS = new ConcurrentHashMap <>();
@@ -1275,7 +1286,7 @@ static class TypeHints {
1275
1286
* @return {@link ByteArrayOutput} as default when no matching {@link CommandOutput} available.
1276
1287
*/
1277
1288
@ SuppressWarnings ("rawtypes" )
1278
- public CommandOutput getTypeHint (CommandType type ) {
1289
+ public CommandOutput getTypeHint (ProtocolKeyword type ) {
1279
1290
return getTypeHint (type , new ByteArrayOutput <>(CODEC ));
1280
1291
}
1281
1292
@@ -1286,7 +1297,7 @@ public CommandOutput getTypeHint(CommandType type) {
1286
1297
* @return
1287
1298
*/
1288
1299
@ SuppressWarnings ("rawtypes" )
1289
- public CommandOutput getTypeHint (CommandType type , CommandOutput defaultType ) {
1300
+ public CommandOutput getTypeHint (ProtocolKeyword type , CommandOutput defaultType ) {
1290
1301
1291
1302
if (type == null || !COMMAND_OUTPUT_TYPE_MAPPING .containsKey (type )) {
1292
1303
return defaultType ;
@@ -1407,7 +1418,7 @@ static PipeliningFlushPolicy buffered(int bufferSize) {
1407
1418
1408
1419
/**
1409
1420
* State object associated with flushing of the currently ongoing pipeline.
1410
- *
1421
+ *
1411
1422
* @author Mark Paluch
1412
1423
* @since 2.3
1413
1424
*/
@@ -1440,7 +1451,7 @@ public interface PipeliningFlushState {
1440
1451
1441
1452
/**
1442
1453
* Implementation to flush on each command.
1443
- *
1454
+ *
1444
1455
* @author Mark Paluch
1445
1456
* @since 2.3
1446
1457
*/
@@ -1465,7 +1476,7 @@ public void onClose(StatefulConnection<?, ?> connection) {}
1465
1476
1466
1477
/**
1467
1478
* Implementation to flush on closing the pipeline.
1468
- *
1479
+ *
1469
1480
* @author Mark Paluch
1470
1481
* @since 2.3
1471
1482
*/
@@ -1497,7 +1508,7 @@ public void onClose(StatefulConnection<?, ?> connection) {
1497
1508
1498
1509
/**
1499
1510
* Pipeline state for buffered flushing.
1500
- *
1511
+ *
1501
1512
* @author Mark Paluch
1502
1513
* @since 2.3
1503
1514
*/
@@ -1529,4 +1540,49 @@ public void onClose(StatefulConnection<?, ?> connection) {
1529
1540
connection .setAutoFlushCommands (true );
1530
1541
}
1531
1542
}
1543
+
1544
+ /**
1545
+ * @since 2.3.8
1546
+ */
1547
+ static class CustomCommandType implements ProtocolKeyword {
1548
+
1549
+ private final String name ;
1550
+
1551
+ CustomCommandType (String name ) {
1552
+ this .name = name ;
1553
+ }
1554
+
1555
+ @ Override
1556
+ public byte [] getBytes () {
1557
+ return name .getBytes (StandardCharsets .US_ASCII );
1558
+ }
1559
+
1560
+ @ Override
1561
+ public String name () {
1562
+ return name ;
1563
+ }
1564
+
1565
+ @ Override
1566
+ public boolean equals (Object o ) {
1567
+
1568
+ if (this == o ) {
1569
+ return true ;
1570
+ }
1571
+ if (!(o instanceof CustomCommandType )) {
1572
+ return false ;
1573
+ }
1574
+ CustomCommandType that = (CustomCommandType ) o ;
1575
+ return ObjectUtils .nullSafeEquals (name , that .name );
1576
+ }
1577
+
1578
+ @ Override
1579
+ public int hashCode () {
1580
+ return ObjectUtils .nullSafeHashCode (name );
1581
+ }
1582
+
1583
+ @ Override
1584
+ public String toString () {
1585
+ return name ;
1586
+ }
1587
+ }
1532
1588
}
0 commit comments