spring-bootspring-datacouchbasespring-cachespring-data-couchbase

How to set Expiration/TTL(Time to Live) for couchbase documents using spring-boot-starter-data-couchbase and spring-boot-starter-cache?


I am working on an OTP (one-time password) provider microservice and I want to cache the OTPs in Couchbase and retrieve them for a given key. I am able to achieve this using the following pieces of code. But I am not able to implement one final feature, which is, the OTP should be short-lived and should get automatically evicted from the cache after a certain configurable interval.

I am using the following dependencies -

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-couchbase</artifactId>
        </dependency>

and I have configured a CacheConfig as follows -

@Configuration
public class CacheConfig {

    @Value("${couchbase.url}")
    private String url;

    @Value("${couchbase.username}")
    private String username;

    @Value("${couchbase.password}")
    private String password;

    @Value("${couchbase.bucket}")
    private String bucket;

    public static final String CACHE_NAME ="otp-cache";

    @Bean(destroyMethod = "disconnect")
    public Cluster cluster() {
        return Cluster.connect(url, username, password);
    }

    @Bean
    public CacheManager cacheManager() {
        return CouchbaseCacheManager.create(new SimpleCouchbaseClientFactory(cluster(), bucket, null));
    }
}

finally in my service class, where i generate the OTP, I am using the @Cacheable annotation as follows -

@Cacheable(cacheNames = CacheConfig.CACHE_NAME, key = "'provider_'+#key")
    @Override
    public Integer generateOTP(String key) {
        StringBuilder generatedOTP = new StringBuilder();
        SecureRandom secureRandom = new SecureRandom();
        LOGGER.info("generating OTP for provider(not from cache) - "+key);
        try {
            secureRandom = SecureRandom.getInstance(secureRandom.getAlgorithm());
            for (int i = 0; i < LENGTH_OF_OTP; i++) {
                generatedOTP.append(secureRandom.nextInt(9));
            }
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("exception occurred in generating OTP");
        }
        return Integer.parseInt(generatedOTP.toString());
    }

I have come across some solutions which suggests using the @CacheEvict annotation with a @Scheduled method, but it will clear the entire cache and not just expired entries. I have also tried wrapping the response of the @Cacheable method in a serializable object and used the @Document(expiryExpression = and @Expiry annotation, but that does not work either, additionally, I get some class cast exception when the object is fetched from the cache and spring tries to deserialize it to the pojo class.

I also see this property using my IDE's auto-suggestion in application-properties file spring.cache.couchbase.expiration=, but this doesn't work either.

How do I set an expiration time for each otp cached in the couchbase bucket?


Solution

  • For a lifetime of 60 minutes, use

    CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofMinutes(60))

    https://docs.spring.io/spring-data/couchbase/reference/couchbase/caching.html