Skip to content

Commit 3800095

Browse files
ggivotishun
andauthored
Hash Field Expiration (part II) (#3195) (#3204)
* Bump default client-libs-test container version * Support HGETDEL * Support HSETEX, HGETEX * format & clean up unintended formating from autogenerated api * fix AbstractRedisReactiveCommands::hgetex streaming API * Address review comments - @SInCE 6.7.0 -> 6.6 - Remove long/Date methods for settin timestamp * Update src/test/java/io/lettuce/core/RedisCommandBuilderUnitTests.java Co-authored-by: Tihomir Krasimirov Mateev <[email protected]> --------- Co-authored-by: Tihomir Krasimirov Mateev <[email protected]>
1 parent e79e037 commit 3800095

17 files changed

+1251
-3
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,41 @@ public RedisFuture<Long> hset(K key, Map<K, V> map) {
14291429
return dispatch(commandBuilder.hset(key, map));
14301430
}
14311431

1432+
@Override
1433+
public RedisFuture<Long> hsetex(K key, Map<K, V> map) {
1434+
return dispatch(commandBuilder.hsetex(key, map));
1435+
}
1436+
1437+
@Override
1438+
public RedisFuture<Long> hsetex(K key, HSetExArgs hSetExArgs, Map<K, V> map) {
1439+
return dispatch(commandBuilder.hsetex(key, hSetExArgs, map));
1440+
}
1441+
1442+
@Override
1443+
public RedisFuture<List<KeyValue<K, V>>> hgetex(K key, K... fields) {
1444+
return dispatch(commandBuilder.hgetex(key, fields));
1445+
}
1446+
1447+
@Override
1448+
public RedisFuture<List<KeyValue<K, V>>> hgetex(K key, HGetExArgs hGetExArgs, K... fields) {
1449+
return dispatch(commandBuilder.hgetex(key, hGetExArgs, fields));
1450+
}
1451+
1452+
@Override
1453+
public RedisFuture<Long> hgetex(KeyValueStreamingChannel<K, V> channel, K key, HGetExArgs hGetExArgs, K... fields) {
1454+
return dispatch(commandBuilder.hgetex(channel, key, hGetExArgs, fields));
1455+
}
1456+
1457+
@Override
1458+
public RedisFuture<List<KeyValue<K, V>>> hgetdel(K key, K... fields) {
1459+
return dispatch(commandBuilder.hgetdel(key, fields));
1460+
}
1461+
1462+
@Override
1463+
public RedisFuture<Long> hgetdel(KeyValueStreamingChannel<K, V> channel, K key, K... fields) {
1464+
return dispatch(commandBuilder.hgetdel(channel, key, fields));
1465+
}
1466+
14321467
@Override
14331468
public RedisFuture<Boolean> hsetnx(K key, K field, V value) {
14341469
return dispatch(commandBuilder.hsetnx(key, field, value));

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,41 @@ public Mono<Long> hset(K key, Map<K, V> map) {
14941494
return createMono(() -> commandBuilder.hset(key, map));
14951495
}
14961496

1497+
@Override
1498+
public Mono<Long> hsetex(K key, Map<K, V> map) {
1499+
return createMono(() -> commandBuilder.hsetex(key, map));
1500+
}
1501+
1502+
@Override
1503+
public Mono<Long> hsetex(K key, HSetExArgs hSetExArgs, Map<K, V> map) {
1504+
return createMono(() -> commandBuilder.hsetex(key, hSetExArgs, map));
1505+
}
1506+
1507+
@Override
1508+
public Flux<KeyValue<K, V>> hgetex(K key, K... fields) {
1509+
return createDissolvingFlux(() -> commandBuilder.hgetex(key, fields));
1510+
}
1511+
1512+
@Override
1513+
public Flux<KeyValue<K, V>> hgetex(K key, HGetExArgs hGetExArgs, K... fields) {
1514+
return createDissolvingFlux(() -> commandBuilder.hgetex(key, hGetExArgs, fields));
1515+
}
1516+
1517+
@Override
1518+
public Mono<Long> hgetex(KeyValueStreamingChannel<K, V> channel, K key, HGetExArgs hGetExArgs, K... fields) {
1519+
return createMono(() -> commandBuilder.hgetex(channel, key, hGetExArgs, fields));
1520+
}
1521+
1522+
@Override
1523+
public Flux<KeyValue<K, V>> hgetdel(K key, K... fields) {
1524+
return createDissolvingFlux(() -> commandBuilder.hgetdel(key, fields));
1525+
}
1526+
1527+
@Override
1528+
public Mono<Long> hgetdel(KeyValueStreamingChannel<K, V> channel, K key, K... fields) {
1529+
return createMono(() -> commandBuilder.hgetdel(channel, key, fields));
1530+
}
1531+
14971532
@Override
14981533
public Mono<Boolean> hsetnx(K key, K field, V value) {
14991534
return createMono(() -> commandBuilder.hsetnx(key, field, value));
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package io.lettuce.core;
2+
3+
import io.lettuce.core.internal.LettuceAssert;
4+
import io.lettuce.core.protocol.CommandArgs;
5+
import io.lettuce.core.protocol.CommandType;
6+
7+
import java.time.Duration;
8+
import java.time.Instant;
9+
import java.util.Date;
10+
11+
/**
12+
* Argument list builder for the Redis <a href="https://redis.io/commands/getex">HGETEX</a> command starting from Redis 8.0.
13+
* Static import the methods from {@link Builder} and chain the method calls: {@code ex(10).nx()}.
14+
* <p>
15+
* {@link HGetExArgs} is a mutable object and instances should be used only once to avoid shared mutable state.
16+
*
17+
* @author Ivo Gaydajiev
18+
* @since 6.6
19+
*/
20+
public class HGetExArgs implements CompositeArgument {
21+
22+
private Long ex;
23+
24+
private Long exAt;
25+
26+
private Long px;
27+
28+
private Long pxAt;
29+
30+
private boolean persist = false;
31+
32+
/**
33+
* Builder entry points for {@link HGetExArgs}.
34+
*/
35+
public static class Builder {
36+
37+
/**
38+
* Utility constructor.
39+
*/
40+
private Builder() {
41+
}
42+
43+
/**
44+
* Creates new {@link HGetExArgs} and enable {@literal EX}.
45+
*
46+
* @param timeout expire time in seconds.
47+
* @return new {@link HGetExArgs} with {@literal EX} enabled.
48+
* @see HGetExArgs#ex(long)
49+
* @since 6.6
50+
*/
51+
public static HGetExArgs ex(Duration timeout) {
52+
return new HGetExArgs().ex(timeout);
53+
}
54+
55+
/**
56+
* Creates new {@link HGetExArgs} and enable {@literal EXAT}.
57+
*
58+
* @param timestamp the timestamp type: posix time in seconds.
59+
* @return new {@link HGetExArgs} with {@literal EXAT} enabled.
60+
* @see HGetExArgs#exAt(Instant)
61+
* @since 6.6
62+
*/
63+
public static HGetExArgs exAt(Instant timestamp) {
64+
return new HGetExArgs().exAt(timestamp);
65+
}
66+
67+
/**
68+
* Creates new {@link HGetExArgs} and enable {@literal PX}.
69+
*
70+
* @param timeout expire time in milliseconds.
71+
* @return new {@link HGetExArgs} with {@literal PX} enabled.
72+
* @see HGetExArgs#px(long)
73+
* @since 6.6
74+
*/
75+
public static HGetExArgs px(Duration timeout) {
76+
return new HGetExArgs().px(timeout);
77+
}
78+
79+
/**
80+
* Creates new {@link HGetExArgs} and enable {@literal PXAT}.
81+
*
82+
* @param timestamp the timestamp type: posix time.
83+
* @return new {@link HGetExArgs} with {@literal PXAT} enabled.
84+
* @see HGetExArgs#pxAt(Instant)
85+
* @since 6.6
86+
*/
87+
public static HGetExArgs pxAt(Instant timestamp) {
88+
return new HGetExArgs().pxAt(timestamp);
89+
}
90+
91+
/**
92+
* Creates new {@link HGetExArgs} and enable {@literal PERSIST}.
93+
*
94+
* @return new {@link HGetExArgs} with {@literal PERSIST} enabled.
95+
* @see HGetExArgs#persist()
96+
*/
97+
public static HGetExArgs persist() {
98+
return new HGetExArgs().persist();
99+
}
100+
101+
}
102+
103+
/**
104+
* Set the specified expire time, in seconds.
105+
*
106+
* @param timeout expire time in seconds.
107+
* @return {@code this} {@link HGetExArgs}.
108+
* @since 6.6
109+
*/
110+
public HGetExArgs ex(Duration timeout) {
111+
112+
LettuceAssert.notNull(timeout, "Timeout must not be null");
113+
114+
this.ex = timeout.getSeconds();
115+
return this;
116+
}
117+
118+
/**
119+
* Set the specified expire at time using a posix {@code timestamp}.
120+
*
121+
* @param timestamp the timestamp type: posix time in seconds.
122+
* @return {@code this} {@link HGetExArgs}.
123+
* @since 6.6
124+
*/
125+
public HGetExArgs exAt(Instant timestamp) {
126+
127+
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
128+
this.exAt = timestamp.getEpochSecond();
129+
return this;
130+
}
131+
132+
/**
133+
* Set the specified expire time, in milliseconds.
134+
*
135+
* @param timeout expire time in milliseconds.
136+
* @return {@code this} {@link HGetExArgs}.
137+
*/
138+
public HGetExArgs px(Duration timeout) {
139+
140+
LettuceAssert.notNull(timeout, "Timeout must not be null");
141+
142+
this.px = timeout.toMillis();
143+
return this;
144+
}
145+
146+
/**
147+
* Set the specified expire at time using a posix {@code timestamp}.
148+
*
149+
* @param timestamp the timestamp type: posix time in milliseconds.
150+
* @return {@code this} {@link HGetExArgs}.
151+
* @since 6.6
152+
*/
153+
public HGetExArgs pxAt(Instant timestamp) {
154+
155+
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
156+
157+
this.pxAt = timestamp.toEpochMilli();
158+
return this;
159+
}
160+
161+
/**
162+
* Remove the time to live associated with the key.
163+
*
164+
* @return {@code this} {@link HGetExArgs}.
165+
*/
166+
public HGetExArgs persist() {
167+
168+
this.persist = true;
169+
return this;
170+
}
171+
172+
@Override
173+
public <K, V> void build(CommandArgs<K, V> args) {
174+
175+
if (ex != null) {
176+
args.add("EX").add(ex);
177+
}
178+
179+
if (exAt != null) {
180+
args.add("EXAT").add(exAt);
181+
}
182+
183+
if (px != null) {
184+
args.add("PX").add(px);
185+
}
186+
187+
if (pxAt != null) {
188+
args.add("PXAT").add(pxAt);
189+
}
190+
191+
if (persist) {
192+
args.add(CommandType.PERSIST);
193+
}
194+
}
195+
196+
}

0 commit comments

Comments
 (0)