Skip to content

Commit 6a67e42

Browse files
Introduce HGETDEL command to the Spring Data Redis framework
Signed-off-by: viktoriya.kutsarova <viktoriya.kutsarova@redis.com>
1 parent 396711e commit 6a67e42

24 files changed

+781
-4
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
VERSION?=7.4.0
15+
VERSION?=8.0.0
1616
PROJECT?=redis
1717
GH_ORG?=redis
1818
SPRING_PROFILE?=ci

src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.apache.commons.logging.Log;
2525
import org.apache.commons.logging.LogFactory;
26+
import org.jetbrains.annotations.NotNull;
2627
import org.jspecify.annotations.NullUnmarked;
2728
import org.jspecify.annotations.Nullable;
2829
import org.springframework.core.convert.converter.Converter;
@@ -1609,6 +1610,11 @@ public List<String> hVals(String key) {
16091610
return convertAndReturn(delegate.hVals(serialize(key)), byteListToStringList);
16101611
}
16111612

1613+
@Override
1614+
public List<String> hGetDel(String key, String... fields) {
1615+
return convertAndReturn(delegate.hGetDel(serialize(key), serializeMulti(fields)), byteListToStringList);
1616+
}
1617+
16121618
@Override
16131619
public Long incr(String key) {
16141620
return incr(serialize(key));
@@ -2582,6 +2588,11 @@ public List<Long> hTtl(byte[] key, TimeUnit timeUnit, byte[]... fields) {
25822588
return this.delegate.hTtl(key, timeUnit, fields);
25832589
}
25842590

2591+
@Override
2592+
public List<byte[]> hGetDel(@NotNull byte[] key, @NotNull byte[]... fields) {
2593+
return convertAndReturn(delegate.hGetDel(key, fields), Converters.identityConverter());
2594+
}
2595+
25852596
public @Nullable List<Long> applyExpiration(String key,
25862597
org.springframework.data.redis.core.types.Expiration expiration,
25872598
ExpirationOptions options, String... fields) {

src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,13 @@ default List<Long> hpTtl(byte[] key, byte[]... fields) {
15941594
return hashCommands().hpTtl(key, fields);
15951595
}
15961596

1597+
/** @deprecated in favor of {@link RedisConnection#hashCommands()}}. */
1598+
@Override
1599+
@Deprecated
1600+
default List<byte[]> hGetDel(byte[] key, byte[]... fields) {
1601+
return hashCommands().hGetDel(key, fields);
1602+
}
1603+
15971604
/** @deprecated in favor of {@link RedisConnection#hashCommands()}}. */
15981605
@Override
15991606
@Deprecated

src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public interface ReactiveHashCommands {
5858
*
5959
* @author Christoph Strobl
6060
* @author Tihomir Mateev
61+
* @author Viktoriya Kutsarova
6162
*/
6263
class HashFieldsCommand extends KeyCommand {
6364

@@ -1255,4 +1256,86 @@ default Flux<Long> hpTtl(ByteBuffer key, List<ByteBuffer> fields) {
12551256
*/
12561257
Flux<NumericResponse<HashFieldsCommand, Long>> hpTtl(Publisher<HashFieldsCommand> commands);
12571258

1259+
1260+
/**
1261+
* {@literal HGETDEL} {@link Command}.
1262+
*
1263+
* @author Viktoriya Kutsarova
1264+
* @see <a href="https://redis.io/commands/hgetdel">Redis Documentation: HGETDEL</a>
1265+
*/
1266+
class HGetDelCommand extends HashFieldsCommand {
1267+
1268+
private HGetDelCommand(@Nullable ByteBuffer key, List<ByteBuffer> fields) {
1269+
super(key, fields);
1270+
}
1271+
1272+
/**
1273+
* Creates a new {@link HGetDelCommand} given a {@link ByteBuffer field name}.
1274+
*
1275+
* @param field must not be {@literal null}.
1276+
* @return a new {@link HGetDelCommand} for a {@link ByteBuffer field name}.
1277+
*/
1278+
public static HGetDelCommand field(ByteBuffer field) {
1279+
1280+
Assert.notNull(field, "Field must not be null");
1281+
1282+
return new HGetDelCommand(null, Collections.singletonList(field));
1283+
}
1284+
1285+
/**
1286+
* Creates a new {@link HGetDelCommand} given a {@link Collection} of field names.
1287+
*
1288+
* @param fields must not be {@literal null}.
1289+
* @return a new {@link HGetDelCommand} for a {@link Collection} of field names.
1290+
*/
1291+
public static HGetDelCommand fields(Collection<ByteBuffer> fields) {
1292+
1293+
Assert.notNull(fields, "Fields must not be null");
1294+
1295+
return new HGetDelCommand(null, new ArrayList<>(fields));
1296+
}
1297+
1298+
/**
1299+
* Applies the hash {@literal key}. Constructs a new command instance with all previously configured properties.
1300+
*
1301+
* @param key must not be {@literal null}.
1302+
* @return a new {@link HGetDelCommand} with {@literal key} applied.
1303+
*/
1304+
public HGetDelCommand from(ByteBuffer key) {
1305+
1306+
Assert.notNull(key, "Key must not be null");
1307+
1308+
return new HGetDelCommand(key, getFields());
1309+
}
1310+
}
1311+
1312+
1313+
/**
1314+
* Get and delete the value of one or more {@literal fields} from hash at {@literal key}. Values are returned in the
1315+
* order of the requested keys. Absent field values are represented using {@literal null} in the resulting {@link List}.
1316+
* When the last field is deleted, the key will also be deleted.
1317+
*
1318+
* @param key must not be {@literal null}.
1319+
* @param fields must not be {@literal null}.
1320+
* @return never {@literal null}.
1321+
* @see <a href="https://redis.io/commands/hgetdel">Redis Documentation: HGETDEL</a>
1322+
*/
1323+
default Mono<List<ByteBuffer>> hGetDel(ByteBuffer key, Collection<ByteBuffer> fields) {
1324+
1325+
Assert.notNull(key, "Key must not be null");
1326+
Assert.notNull(fields, "Fields must not be null");
1327+
1328+
return hGetDel(Mono.just(HGetDelCommand.fields(fields).from(key))).next().map(MultiValueResponse::getOutput);
1329+
}
1330+
1331+
/**
1332+
* Get and delete the value of one or more {@literal fields} from hash at {@literal key}. Values are returned in the
1333+
* order of the requested keys. Absent field values are represented using {@literal null} in the resulting {@link List}.
1334+
* When the last field is deleted, the key will also be deleted.
1335+
*
1336+
* @param commands must not be {@literal null}.
1337+
* @return never {@literal null}.
1338+
* @see <a href="https://redis.io/commands/hgetdel">Redis Documentation: HGETDEL</a>
1339+
*/
1340+
Flux<MultiValueResponse<HGetDelCommand, ByteBuffer>> hGetDel(Publisher<HGetDelCommand> commands);
12581341
}

src/main/java/org/springframework/data/redis/connection/RedisHashCommands.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
* @author Christoph Strobl
3535
* @author Mark Paluch
3636
* @author Tihomir Mateev
37+
* @author Viktoriya Kutsarova
3738
* @see RedisCommands
3839
*/
3940
@NullUnmarked
@@ -541,4 +542,16 @@ default List<Long> hExpireAt(byte @NonNull [] key, long unixTime, byte @NonNull
541542
* @since 3.5
542543
*/
543544
List<@NonNull Long> hpTtl(byte @NonNull [] key, byte @NonNull [] @NonNull... fields);
545+
546+
/**
547+
* Get and delete the value of one or more {@code fields} from hash at {@code key}. Values are returned in the order of
548+
* the requested keys. Absent field values are represented using {@literal null} in the resulting {@link List}.
549+
* When the last field is deleted, the key will also be deleted.
550+
*
551+
* @param key must not be {@literal null}.
552+
* @param fields must not be {@literal null}.
553+
* @return empty {@link List} if key does not exist. {@literal null} when used in pipeline / transaction.
554+
* @see <a href="https://redis.io/commands/hgetdel">Redis Documentation: HGETDEL</a>
555+
*/
556+
List<byte[]> hGetDel(byte @NonNull [] key, byte @NonNull [] @NonNull... fields);
544557
}

src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,18 @@ List<Long> hpExpireAt(@NonNull String key, long unixTimeInMillis, ExpirationOpti
25522552
*/
25532553
List<Long> hpTtl(@NonNull String key, @NonNull String @NonNull... fields);
25542554

2555+
/**
2556+
* Get and delete the value of one or more {@code fields} from hash at {@code key}. When the last field is deleted,
2557+
* the key will also be deleted.
2558+
*
2559+
* @param key must not be {@literal null}.
2560+
* @param fields must not be {@literal null}.
2561+
* @return empty {@link List} if key does not exist. {@literal null} when used in pipeline / transaction.
2562+
* @see <a href="https://redis.io/commands/hmget">Redis Documentation: HMGET</a>
2563+
* @see RedisHashCommands#hMGet(byte[], byte[]...)
2564+
*/
2565+
List<String> hGetDel(@NonNull String key, @NonNull String @NonNull... fields);
2566+
25552567
// -------------------------------------------------------------------------
25562568
// Methods dealing with HyperLogLog
25572569
// -------------------------------------------------------------------------

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterHashCommands.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,20 @@ public List<Long> hpTtl(byte[] key, byte[]... fields) {
414414
}
415415
}
416416

417+
@Override
418+
public List<byte[]> hGetDel(byte[] key, byte[]... fields) {
419+
420+
Assert.notNull(key, "Key must not be null");
421+
Assert.notNull(fields, "Fields must not be null");
422+
423+
try {
424+
return connection.getCluster().hgetdel(key, fields);
425+
} catch (Exception ex) {
426+
throw convertJedisAccessException(ex);
427+
}
428+
429+
}
430+
417431
@Nullable
418432
@Override
419433
public Long hStrLen(byte[] key, byte[] field) {

src/main/java/org/springframework/data/redis/connection/jedis/JedisHashCommands.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,15 @@ protected void doClose() {
332332
return connection.invoke().just(Jedis::hpttl, PipelineBinaryCommands::hpttl, key, fields);
333333
}
334334

335+
@Override
336+
public List<byte[]> hGetDel(byte @NonNull [] key, byte @NonNull [] @NonNull... fields) {
337+
338+
Assert.notNull(key, "Key must not be null");
339+
Assert.notNull(fields, "Fields must not be null");
340+
341+
return connection.invoke().just(Jedis::hgetdel, PipelineBinaryCommands::hgetdel, key, fields);
342+
}
343+
335344
@Nullable
336345
@Override
337346
public Long hStrLen(byte[] key, byte[] field) {

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,7 @@ static class TypeHints {
12431243
COMMAND_OUTPUT_TYPE_MAPPING.put(ZRANGEBYSCORE, ValueListOutput.class);
12441244
COMMAND_OUTPUT_TYPE_MAPPING.put(ZREVRANGE, ValueListOutput.class);
12451245
COMMAND_OUTPUT_TYPE_MAPPING.put(ZREVRANGEBYSCORE, ValueListOutput.class);
1246+
COMMAND_OUTPUT_TYPE_MAPPING.put(HGETDEL, ValueListOutput.class);
12461247

12471248
// BOOLEAN
12481249
COMMAND_OUTPUT_TYPE_MAPPING.put(EXISTS, BooleanOutput.class);

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceHashCommands.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,16 @@ public List<Long> hpTtl(byte @NonNull [] key, byte @NonNull [] @NonNull... field
265265
return connection.invoke().fromMany(RedisHashAsyncCommands::hpttl, key, fields).toList();
266266
}
267267

268+
@Override
269+
public List<byte[]> hGetDel(byte @NonNull [] key, byte @NonNull []... fields) {
270+
271+
Assert.notNull(key, "Key must not be null");
272+
Assert.notNull(fields, "Fields must not be null");
273+
274+
return connection.invoke().fromMany(RedisHashAsyncCommands::hgetdel, key, fields)
275+
.toList(source -> source.getValueOrElse(null));
276+
}
277+
268278
/**
269279
* @param key
270280
* @param cursorId

0 commit comments

Comments
 (0)