Skip to content

Commit b921774

Browse files
committed
Refactor ValueCondition
1 parent 29b48eb commit b921774

File tree

6 files changed

+134
-108
lines changed

6 files changed

+134
-108
lines changed

src/main/java/io/lettuce/core/RedisCommandBuilder.java

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ Command<K, V, Long> delex(K key, ValueCondition<V> condition) {
945945
LettuceAssert.notNull(condition, "ValueCondition " + MUST_NOT_BE_NULL);
946946

947947
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
948-
buildConditionArgs(args, condition);
948+
condition.build(args);
949949
return createCommand(DELEX, new IntegerOutput<>(codec), args);
950950
}
951951

@@ -2723,7 +2723,7 @@ Command<K, V, String> set(K key, V value, ValueCondition<V> condition) {
27232723
LettuceAssert.notNull(condition, "ValueCondition " + MUST_NOT_BE_NULL);
27242724

27252725
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).addValue(value);
2726-
buildConditionArgs(args, condition);
2726+
condition.build(args);
27272727
return createCommand(SET, new StatusOutput<>(codec), args);
27282728
}
27292729

@@ -2734,7 +2734,7 @@ Command<K, V, String> set(K key, V value, SetArgs setArgs, ValueCondition<V> con
27342734

27352735
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).addValue(value);
27362736
setArgs.build(args);
2737-
buildConditionArgs(args, condition);
2737+
condition.build(args);
27382738
return createCommand(SET, new StatusOutput<>(codec), args);
27392739
}
27402740

@@ -2743,7 +2743,7 @@ Command<K, V, V> setGet(K key, V value, ValueCondition<V> condition) {
27432743
LettuceAssert.notNull(condition, "ValueCondition " + MUST_NOT_BE_NULL);
27442744

27452745
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).addValue(value);
2746-
buildConditionArgs(args, condition);
2746+
condition.build(args);
27472747
args.add(GET);
27482748
return createCommand(SET, new ValueOutput<>(codec), args);
27492749
}
@@ -2755,7 +2755,7 @@ Command<K, V, V> setGet(K key, V value, SetArgs setArgs, ValueCondition<V> condi
27552755

27562756
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).addValue(value);
27572757
setArgs.build(args);
2758-
buildConditionArgs(args, condition);
2758+
condition.build(args);
27592759
args.add(GET);
27602760
return createCommand(SET, new ValueOutput<>(codec), args);
27612761
}
@@ -4622,33 +4622,6 @@ Command<K, V, StreamScanCursor> zscanStreaming(ScoredValueStreamingChannel<V> ch
46224622
return zscanStreaming(channel, key, ScanCursor.INITIAL, scanArgs);
46234623
}
46244624

4625-
private void buildConditionArgs(CommandArgs<K, V> args, ValueCondition<V> condition) {
4626-
switch (condition.kind()) {
4627-
case EXISTS:
4628-
args.add(XX);
4629-
break;
4630-
case NOT_EXISTS:
4631-
args.add(NX);
4632-
break;
4633-
case EQUAL:
4634-
args.add(IFEQ).addValue(condition.value());
4635-
break;
4636-
case NOT_EQUAL:
4637-
args.add(IFNE).addValue(condition.value());
4638-
break;
4639-
case DIGEST_EQUAL:
4640-
args.add(IFDEQ).add(condition.digestHex());
4641-
break;
4642-
case DIGEST_NOT_EQUAL:
4643-
args.add(IFDNE).add(condition.digestHex());
4644-
break;
4645-
case ALWAYS:
4646-
default:
4647-
// no additional args
4648-
break;
4649-
}
4650-
}
4651-
46524625
Command<K, V, StreamScanCursor> zscanStreaming(ScoredValueStreamingChannel<V> channel, K key, ScanCursor scanCursor,
46534626
ScanArgs scanArgs) {
46544627
notNullKey(key);

src/main/java/io/lettuce/core/ValueCondition.java

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package io.lettuce.core;
2121

2222
import io.lettuce.core.annotations.Experimental;
23+
import io.lettuce.core.protocol.CommandArgs;
24+
import io.lettuce.core.protocol.CommandKeyword;
2325

2426
/**
2527
* A compare condition to be used with commands that support conditional value checks (e.g. SET with IFEQ/IFNE/IFDEQ/IFDNE and
@@ -38,20 +40,39 @@ public final class ValueCondition<V> {
3840
* The kind of condition represented by this instance.
3941
*/
4042
public enum Kind {
41-
/** unconditional */
42-
ALWAYS,
43-
/** key must exist */
44-
EXISTS,
45-
/** key must not exist */
46-
NOT_EXISTS,
43+
4744
/** current value must equal provided value */
48-
EQUAL,
45+
EQUAL(CommandKeyword.IFEQ, Param.VALUE),
4946
/** current value must not equal provided value */
50-
NOT_EQUAL,
47+
NOT_EQUAL(CommandKeyword.IFNE, Param.VALUE),
5148
/** current value's digest must equal provided digest */
52-
DIGEST_EQUAL,
49+
DIGEST_EQUAL(CommandKeyword.IFDEQ, Param.DIGEST),
5350
/** current value's digest must not equal provided digest */
54-
DIGEST_NOT_EQUAL
51+
DIGEST_NOT_EQUAL(CommandKeyword.IFDNE, Param.DIGEST);
52+
53+
private final CommandKeyword keyword;
54+
55+
private final Param param;
56+
57+
Kind(CommandKeyword keyword, Param param) {
58+
this.keyword = keyword;
59+
this.param = param;
60+
}
61+
62+
/** The protocol keyword to emit for this condition. */
63+
public CommandKeyword keyword() {
64+
return keyword;
65+
}
66+
67+
/** Indicates whether this condition uses a value or a digest parameter. */
68+
public Param param() {
69+
return param;
70+
}
71+
}
72+
73+
/** Parameter kind for condition arguments. */
74+
enum Param {
75+
VALUE, DIGEST
5576
}
5677

5778
private final Kind kind;
@@ -66,45 +87,53 @@ private ValueCondition(Kind kind, V value, String digestHex) {
6687
this.digestHex = digestHex;
6788
}
6889

69-
/** A condition that always applies (no comparison). */
70-
public static <V> ValueCondition<V> always() {
71-
return new ValueCondition<>(Kind.ALWAYS, null, null);
72-
73-
}
74-
75-
/** A condition that requires the key to exist (equivalent to XX in SET). */
76-
public static <V> ValueCondition<V> exists() {
77-
return new ValueCondition<>(Kind.EXISTS, null, null);
78-
}
79-
80-
/** A condition that requires the key to not exist (equivalent to NX in SET). */
81-
public static <V> ValueCondition<V> notExists() {
82-
return new ValueCondition<>(Kind.NOT_EXISTS, null, null);
90+
/**
91+
* Append this condition's protocol arguments to the given args.
92+
*/
93+
public <K> void build(CommandArgs<K, V> args) {
94+
args.add(kind.keyword());
95+
switch (kind.param()) {
96+
case VALUE:
97+
args.addValue(value);
98+
break;
99+
case DIGEST:
100+
args.add(digestHex);
101+
break;
102+
default:
103+
break;
104+
}
83105
}
84106

85-
/** A value-based comparison: set/delete only if the current value equals {@code value}. */
86-
public static <V> ValueCondition<V> equal(V value) {
107+
// Factory methods for creating value- and digest-based conditions
108+
/** Create a value-based equality condition; succeeds only if the current value equals the given value. */
109+
public static <V> ValueCondition<V> valueEq(V value) {
87110
if (value == null)
88111
throw new IllegalArgumentException("value must not be null");
89112
return new ValueCondition<>(Kind.EQUAL, value, null);
90113
}
91114

92-
/** A value-based comparison: set/delete only if the current value does not equal {@code value}. */
93-
public static <V> ValueCondition<V> notEqual(V value) {
115+
/** Create a value-based inequality condition; succeeds only if the current value does not equal the given value. */
116+
public static <V> ValueCondition<V> valueNe(V value) {
94117
if (value == null)
95118
throw new IllegalArgumentException("value must not be null");
96119
return new ValueCondition<>(Kind.NOT_EQUAL, value, null);
97120
}
98121

99-
/** A digest-based comparison: set/delete only if the current value's digest equals {@code hex16Digest}. */
100-
public static <V> ValueCondition<V> digestEqualHex(String hex16Digest) {
122+
/**
123+
* Create a digest-based equality condition; succeeds only if the current value's digest matches the given 16-character
124+
* lower-case hex digest.
125+
*/
126+
public static <V> ValueCondition<V> digestEq(String hex16Digest) {
101127
if (hex16Digest == null)
102128
throw new IllegalArgumentException("digest must not be null");
103129
return new ValueCondition<>(Kind.DIGEST_EQUAL, null, hex16Digest);
104130
}
105131

106-
/** A digest-based comparison: set/delete only if the current value's digest does not equal {@code hex16Digest}. */
107-
public static <V> ValueCondition<V> digestNotEqualHex(String hex16Digest) {
132+
/**
133+
* Create a digest-based inequality condition; succeeds only if the current value's digest does not match the given
134+
* 16-character lower-case hex digest.
135+
*/
136+
public static <V> ValueCondition<V> digestNe(String hex16Digest) {
108137
if (hex16Digest == null)
109138
throw new IllegalArgumentException("digest must not be null");
110139
return new ValueCondition<>(Kind.DIGEST_NOT_EQUAL, null, hex16Digest);

src/test/java/io/lettuce/core/cluster/commands/KeyClusterCommandIntegrationTests.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ void delex_unconditional_and_digest_guarded_cluster() {
111111
redis.set(k, "bar");
112112
String d = redis.digestKey(k);
113113
// wrong condition: digestNotEqualHex (should abort)
114-
assertThat(redis.delex(k, ValueCondition.<String> digestNotEqualHex(d))).isEqualTo(0);
114+
assertThat(redis.delex(k, ValueCondition.digestNe(d))).isEqualTo(0);
115115
assertThat(redis.exists(k)).isEqualTo(1);
116116
// right condition: digestEqualHex (should delete)
117-
assertThat(redis.delex(k, ValueCondition.<String> digestEqualHex(d))).isEqualTo(1);
117+
assertThat(redis.delex(k, ValueCondition.digestEq(d))).isEqualTo(1);
118118
assertThat(redis.exists(k)).isEqualTo(0);
119119
}
120120

@@ -133,14 +133,14 @@ void delex_value_equal_notEqual_cluster() {
133133
String k = "k:delex-eq-cluster";
134134
redis.set(k, "v1");
135135
// wrong equality -> abort
136-
assertThat(redis.delex(k, ValueCondition.equal("nope"))).isEqualTo(0);
136+
assertThat(redis.delex(k, ValueCondition.valueEq("nope"))).isEqualTo(0);
137137
// correct equality -> delete
138-
assertThat(redis.delex(k, ValueCondition.equal("v1"))).isEqualTo(1);
138+
assertThat(redis.delex(k, ValueCondition.valueEq("v1"))).isEqualTo(1);
139139
// not-equal that fails (after deletion, recreate)
140140
redis.set(k, "v2");
141-
assertThat(redis.delex(k, ValueCondition.notEqual("v2"))).isEqualTo(0);
141+
assertThat(redis.delex(k, ValueCondition.valueNe("v2"))).isEqualTo(0);
142142
// not-equal that succeeds
143-
assertThat(redis.delex(k, ValueCondition.notEqual("other"))).isEqualTo(1);
143+
assertThat(redis.delex(k, ValueCondition.valueNe("other"))).isEqualTo(1);
144144
}
145145

146146
}

src/test/java/io/lettuce/core/commands/KeyCommandIntegrationTests.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,10 @@ void delex_unconditional_and_digest_guarded() {
630630
redis.set(k, "bar");
631631
String d = redis.digestKey(k); // new DIGEST command
632632
// wrong condition: digestNotEqualHex (should abort)
633-
assertThat(redis.delex(k, ValueCondition.<String> digestNotEqualHex(d))).isEqualTo(0);
633+
assertThat(redis.delex(k, ValueCondition.digestNe(d))).isEqualTo(0);
634634
assertThat(redis.exists(k)).isEqualTo(1);
635635
// right condition: digestEqualHex (should delete)
636-
assertThat(redis.delex(k, ValueCondition.<String> digestEqualHex(d))).isEqualTo(1);
636+
assertThat(redis.delex(k, ValueCondition.digestEq(d))).isEqualTo(1);
637637
assertThat(redis.exists(k)).isEqualTo(0);
638638
}
639639

@@ -644,14 +644,14 @@ void delex_with_value_equal_notEqual() {
644644
String k = "k:delex-eq";
645645
redis.set(k, "v1");
646646
// wrong equality -> abort
647-
assertThat(redis.delex(k, ValueCondition.equal("nope"))).isEqualTo(0);
647+
assertThat(redis.delex(k, ValueCondition.valueEq("nope"))).isEqualTo(0);
648648
// correct equality -> delete
649-
assertThat(redis.delex(k, ValueCondition.equal("v1"))).isEqualTo(1);
649+
assertThat(redis.delex(k, ValueCondition.valueEq("v1"))).isEqualTo(1);
650650
// not-equal that fails (after deletion, recreate)
651651
redis.set(k, "v2");
652-
assertThat(redis.delex(k, ValueCondition.notEqual("v2"))).isEqualTo(0);
652+
assertThat(redis.delex(k, ValueCondition.valueNe("v2"))).isEqualTo(0);
653653
// not-equal that succeeds
654-
assertThat(redis.delex(k, ValueCondition.notEqual("other"))).isEqualTo(1);
654+
assertThat(redis.delex(k, ValueCondition.valueNe("other"))).isEqualTo(1);
655655
}
656656

657657
@Test
@@ -660,9 +660,8 @@ void delex_on_missing_returns_0_for_any_condition() {
660660
String k = "k:missing";
661661
assertThat(redis.del(k)).isEqualTo(0);
662662

663-
assertThat(redis.delex(k, ValueCondition.exists())).isEqualTo(0);
664-
assertThat(redis.delex(k, ValueCondition.equal("x"))).isEqualTo(0);
665-
assertThat(redis.delex(k, ValueCondition.<String> digestEqualHex("0000000000000000"))).isEqualTo(0);
663+
assertThat(redis.delex(k, ValueCondition.valueEq("x"))).isEqualTo(0);
664+
assertThat(redis.delex(k, ValueCondition.digestEq("0000000000000000"))).isEqualTo(0);
666665
}
667666

668667
}

0 commit comments

Comments
 (0)