How Create Redis Idempotency Manager Service with Spring?

Ozan Akkoca
turkcell
Published in
2 min readDec 14, 2023

As mentioned in previous title;
https://medium.com/@ozanakkoca/how-avoid-idempotency-problem-from-apache-kafka-consumers-with-in-memory-data-structure-store-8083abb40999

Idempotency might be a problem for consuming messages from Kafka,
This problem can cause unexpected results like sending same mails to your customers or doing multiple same service calls and so on.

https://www.waitingforcode.com/data-engineering-patterns/idempotent-consumer-pattern/read

So u can simply create a service with Spring to manage or control the consumers on Topics.

Component

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Component.html

Create a custom bean as a Component for Spring to detect it automatically and then inject them wherever your needed.

@Component
@RequiredArgsConstructor
public class RedisRepository {

private final RedisTemplate<String, MailDto> redisTemplate;

public Optional<MailDto> find(String mailId, String mailName) {
return Optional.ofNullable(redisTemplate.opsForValue().get(defineHeader(mailId, mailName)));
}

public void put(final @NonNull MailDto mailDto) {
redisTemplate.opsForValue().set(defineHeader(mailDto.getmailId(), mailDto.getMailName()), mailDto));
}

public void delete(String mailId, String mailName) {
redisTemplate.delete(defineHeader(mailId, mailName));
}

private String defineHeader(String mailId, String mailName) {
return String.format("Mail:%s:%s", mailName, mailId);
}
}

Service

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Service.html

Create a class as a Service provider for business layer to hold business logic.

@Service
public class RIManager {

private final RedisRepository redisRepository;

public boolean IsMailFoundAndPresentOnRedis(String mailId, String mailName) {
MailDto foundMail = null;

try {
Optional<MailDto> optionalMailDto = this.redisRepository.find(mailId, mailName);
if (optionalMailDto.isPresent()) {
foundMail = (MailDto)optionalMailDto.get();
}
} catch (Exception e) {
}

boolean isFound = foundMail == null;

return isFound;
}

public MailDto PutMailToRedis(String mailId, String mailName) {
MailDto mail = new MailDto();
mail.setmailId(mailId);
mail.setmailName(mailName);

try {
this.redisRepository.put(mail);

} catch (Exception e) {
}

return mail;
}

public boolean DeleteMailFromRedis(String mailId, String mailName) {

try {
this.redisRepository.delete(mailId, mailName);

} catch (Exception e) {
}

return true;
}

public RIManager(final RedisRepository redisRepository) {

this.redisRepository = redisRepository;

}
}

And now use ManagerService on code ;

if (!riManager.IsMailFoundAndPresentOnRedis(maiId, mailName)) {                   
....
}

--

--