Skip to content

ValueOperation setIFAbsent with ttl not working. #2081

Closed
@codeayra

Description

@codeayra

I am using RedisTemplate with LettuceConnection Factory(in spring boot) to set key in Redis with ttl ,
Key is getting Set in redis but its ttl not getting set.

when I try to set ttl using redis-cli , its getting set.

here is the code.
public Boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) { Boolean isSuccess = Boolean.FALSE; String absoluteKey = generateAbsoluteKey(key); log.info("Setting key {} in redis..", absoluteKey); try { String sValue = objectMapper.writeValueAsString(value); redisTemplate.opsForValue() .setIfAbsent(absoluteKey, sValue, timeout, unit); } catch (Exception e) { log.error("Error in saving value to redis cache for key: " + absoluteKey, e); } return isSuccess; }

RedisConfiguration is like following

implementation group: 'org.springframework.data', name: 'spring-data-redis'

`@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
return new LettuceConnectionFactory(hostName, port);
}

@Bean
public RedisTemplate<String, String> redisTemplate() {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    redisTemplate.setConnectionFactory(lettuceConnectionFactory());
    redisTemplate.setExposeConnection(true);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new StringRedisSerializer());
    return redisTemplate;
}`

There is no error on console.
I am using spring-data-redis-2.5.0-M5
redis version I have tried with 6.2 also 4.0 .

Please suggest.

Activity

christophstrobl

christophstrobl commented on Jun 11, 2021

@christophstrobl
Member

I checked DefaultValueOperationsIntegrationTests#testSetIfAbsentWithExpiration for Lettuce and everything seems to work as expected. Maybe you can provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

codeayra

codeayra commented on Jun 11, 2021

@codeayra
Author

I got the problem,
What I am doing first calling setIfAbsent with ttl and its working after that I get the key update its value and calling setIfPresent without ttl and which might be clearing its ttl.

How can I update a key value without clearing its ttl ?

christophstrobl

christophstrobl commented on Jun 11, 2021

@christophstrobl
Member

I see - there's ankeepTtl option on Expiration that allows to do this. But it is not present on ValueOperations so you'd have to call it something like the following on the template.

return execute(connection -> connection.set(rawKey, rawValue, Expiration.keepTtl(), SetOption.ifPresent()), true);

I created #2084 for that.

codeayra

codeayra commented on Jun 11, 2021

@codeayra
Author

Got this this error

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR syntax error

code is

public void update(String key, Object value) {
String absoluteKey = generateAbsoluteKey(key);
String valueString = objectMapper.writeValueAsString(value);
try {
redisTemplate.execute(connection -> connection
.set(rawKey(absoluteKey), rawValue(valueString), Expiration.keepTtl(), RedisStringCommands.SetOption
.ifPresent()), true);

    } catch (Exception e) {
        log.error("Error in saving value to redis cache for key: " + absoluteKey, e);
    }
}

@SuppressWarnings("unchecked")
private byte[] rawKey(Object key) {

    if (keySerializer() == null && key instanceof byte[]) {
        return (byte[]) key;
    }

    return keySerializer().serialize(key);
}

@SuppressWarnings("unchecked")
private byte[] rawValue(Object value) {

    if (valueSerializer() == null && value instanceof byte[]) {
        return (byte[]) value;
    }

    return valueSerializer().serialize(value);
}

@SuppressWarnings("rawtypes")
private RedisSerializer keySerializer() {
    return redisTemplate.getKeySerializer();
}

@SuppressWarnings("rawtypes")
private RedisSerializer valueSerializer() {
    return redisTemplate.getValueSerializer();
}
christophstrobl

christophstrobl commented on Jun 11, 2021

@christophstrobl
Member

KEEPTTL is available as off Redis 6.
Does lettuce tell you more than just ERR syntax error?

codeayra

codeayra commented on Jun 11, 2021

@codeayra
Author

nothing..just this error.

codeayra

codeayra commented on Jun 12, 2021

@codeayra
Author

its working finally with redis 6. Thanks.

1 remaining item

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      ValueOperation setIFAbsent with ttl not working. · Issue #2081 · spring-projects/spring-data-redis