Task 1-2: Listener Idempotency Check via Redis
Phase: 1 - Idempotency Priority: High Module:
batchDepends on: task-1-1 Reference: docs/BountyHunter-Backend/details/feature-prize-allocation/SPEC.md
Background
Sau khi task-1-1 thêm correlationId vào PrizeAllocationData, task này implement idempotency check trong tất cả 9 listeners thông qua shared IdempotencyService.
Tasks
1. Tạo shared IdempotencyService
DI Note:
IdempotencyServicelà@ServiceinjectRedisTemplate<String, String>(hoặcStringRedisTemplate) qua constructor (@RequiredArgsConstructor+finalfield). Đảm bảoRedisTemplate<String, String>bean được khai báo trong@Configurationclass củabatchmodule (hoặc dùngStringRedisTemplateautowire trực tiếp). Mỗi listener injectIdempotencyServicequa constructor.
File mới: batch/service/IdempotencyService.java
@Service
@RequiredArgsConstructor
@Slf4j
public class IdempotencyService {
private final StringRedisTemplate redisTemplate; // hoặc RedisTemplate<String, String>
private static final String KEY_PREFIX = "idempotency:prize-alloc:";
private static final long TTL_SECONDS = 3600;
/**
* Atomically marks correlationId as processed.
* @return true nếu chưa được xử lý (isNew) — OK to proceed
* false nếu duplicate — skip processing
*/
public boolean markAsProcessed(String correlationId) {
String key = KEY_PREFIX + correlationId;
Boolean isNew = redisTemplate.opsForValue()
.setIfAbsent(key, "1", TTL_SECONDS, TimeUnit.SECONDS);
return Boolean.TRUE.equals(isNew);
}
}
2. Apply cho tất cả 9 listeners
Template để apply vào mỗi listener:
// Inject: private final IdempotencyService idempotencyService;
@JmsListener(destination = "${queue.prize-allocation.prize}", ...)
public void onMessage(String messageJson) {
PrizeAllocationData data = convertMessage(messageJson, PrizeAllocationData.class);
if (!idempotencyService.markAsProcessed(data.getCorrelationId())) {
log.warn("[IDEMPOTENCY] Skipping duplicate correlationId={}", data.getCorrelationId());
return; // ACK, không process
}
// existing logic ...
}
- [ ]
JMSPrizeAllocationListener - [ ]
JMSPrizeForStreamerAllocationListener - [ ]
JMSUnlimitedPrizeAllocationListener - [ ]
JMSMissionAllocationListener - [ ]
JMSGachaAllocationListener - [ ]
JMSPresentBoxAllocationListener - [ ]
JMSMKPAllocationListener - [ ]
JMSPresaleAllocationListener - [ ]
JMSNoneAllocationListener
Verification / Acceptance Criteria
- [ ]
IdempotencyService.javatồn tại, compile thành công - [ ] Tất cả 9 listeners inject và gọi
idempotencyService.markAsProcessed()trước khi process - [ ] Duplicate message (cùng
correlationId) → skip, log WARN - [ ]
StringRedisTemplatebean available trongbatchmodule (không lỗi autowire) - [ ] Redis key
idempotency:prize-alloc:{correlationId}có TTL = 3600s (verify quaredis-cli TTL)
Files to Create / Modify
batch/service/IdempotencyService.java(new)- 9 listener files trong
batch/jms/prize_allocation/